Java Wait Until File Deleted waitUntilFileDeleted(File file)

Here you can find the source of waitUntilFileDeleted(File file)

Description

Wait until the file is _really_ deleted on file system.

License

Open Source License

Parameter

Parameter Description
file Deleted file

Return

true if the file was finally deleted, false otherwise

Declaration

private static boolean waitUntilFileDeleted(File file) 

Method Source Code

//package com.java2s;
/*******************************************************************************
 * Copyright (c) 2000, 2015 IBM Corporation and others.
 * All rights reserved. This program and the accompanying materials
 * are made available under the terms of the Eclipse Public License v1.0
 * which accompanies this distribution, and is available at
 * http://www.eclipse.org/legal/epl-v10.html
 *
 * Contributors://from   ww w.  j a  v  a2  s . co  m
 *     IBM Corporation - initial API and implementation
 *     Nina Rinskaya
 *           Fix for https://bugs.eclipse.org/bugs/show_bug.cgi?id=172820.
 *     Stephan Herrmann - Contribution for
 *                        [null] "Annotate" proposals for adding external null annotations to library classes - https://bugs.eclipse.org/458200
 *******************************************************************************/

import java.io.File;

public class Main {
    private static int DELETE_MAX_TIME = 0;
    /**
     * Trace deletion operations while running JDT/Core tests.
     */
    public static boolean DELETE_DEBUG = false;
    /**
     * Maximum of time in ms to wait in deletion operation while running JDT/Core tests.
     * Default is 10 seconds. This number cannot exceed 1 minute (ie. 60000).
     * <br>
     * To avoid too many loops while waiting, the ten first ones are done waiting
     * 10ms before repeating, the ten loops after are done waiting 100ms and
     * the other loops are done waiting 1s...
     */
    public static int DELETE_MAX_WAIT = 10000;

    /**
     * Wait until the file is _really_ deleted on file system.
     *
     * @param file Deleted file
     * @return true if the file was finally deleted, false otherwise
     */
    private static boolean waitUntilFileDeleted(File file) {
        if (DELETE_DEBUG) {
            System.out.println();
            System.out.println("WARNING in test: " + getTestName());
            System.out.println("   - problems occured while deleting " + file);
            printJdtStackTrace(null, 1);
            printFileInfo(file.getParentFile(), 1, -1); // display parent with its children
            System.out.print("   - wait for (" + DELETE_MAX_WAIT + "ms max): ");
        }
        int count = 0;
        int delay = 10; // ms
        int maxRetry = DELETE_MAX_WAIT / delay;
        int time = 0;
        while (count < maxRetry) {
            try {
                count++;
                Thread.sleep(delay);
                time += delay;
                if (time > DELETE_MAX_TIME)
                    DELETE_MAX_TIME = time;
                if (DELETE_DEBUG)
                    System.out.print('.');
                if (file.exists()) {
                    if (file.delete()) {
                        // SUCCESS
                        if (DELETE_DEBUG) {
                            System.out.println();
                            System.out.println("   => file really removed after " + time + "ms (max="
                                    + DELETE_MAX_TIME + "ms)");
                            System.out.println();
                        }
                        return true;
                    }
                }
                if (isFileDeleted(file)) {
                    // SUCCESS
                    if (DELETE_DEBUG) {
                        System.out.println();
                        System.out.println(
                                "   => file disappeared after " + time + "ms (max=" + DELETE_MAX_TIME + "ms)");
                        System.out.println();
                    }
                    return true;
                }
                // Increment waiting delay exponentially
                if (count >= 10 && delay <= 100) {
                    count = 1;
                    delay *= 10;
                    maxRetry = DELETE_MAX_WAIT / delay;
                    if ((DELETE_MAX_WAIT % delay) != 0) {
                        maxRetry++;
                    }
                }
            } catch (InterruptedException ie) {
                break; // end loop
            }
        }
        if (!DELETE_DEBUG) {
            System.out.println();
            System.out.println("WARNING in test: " + getTestName());
            System.out.println("   - problems occured while deleting " + file);
            printJdtStackTrace(null, 1);
            printFileInfo(file.getParentFile(), 1, -1); // display parent with its children
        }
        System.out.println();
        System.out.println("   !!! ERROR: " + file + " was never deleted even after having waited "
                + DELETE_MAX_TIME + "ms!!!");
        System.out.println();
        return false;
    }

    /**
     * Returns the test name from stack elements info.
     *
     * @return The name of the test currently running
     */
    private static String getTestName() {
        StackTraceElement[] elements = new Exception().getStackTrace();
        int idx = 0, length = elements.length;
        while (idx < length && !elements[idx++].getClassName().startsWith("org.eclipse.jdt")) {
            // loop until JDT/Core class appears in the stack
        }
        if (idx < length) {
            StackTraceElement testElement = null;
            while (idx < length && elements[idx].getClassName().startsWith("org.eclipse.jdt")) {
                testElement = elements[idx++];
            }
            if (testElement != null) {
                return testElement.getClassName() + " - " + testElement.getMethodName();
            }
        }
        return "?";
    }

    /**
     * Print stack trace with only JDT elements.
     *
     * @param exception Exception of the stack trace. May be null, then a fake exception is used.
     * @param indent Number of tab to display before the stack elements to display.
     */
    private static void printJdtStackTrace(Exception exception, int indent) {
        String tab = "";
        for (int i = 0; i < indent; i++)
            tab += "\t";
        StackTraceElement[] elements = (exception == null ? new Exception() : exception).getStackTrace();
        int idx = 0, length = elements.length;
        while (idx < length && !elements[idx++].getClassName().startsWith("org.eclipse.jdt")) {
            // loop until JDT/Core class appears in the stack
        }
        if (idx < length) {
            System.out.print(tab + "- stack trace");
            if (exception == null)
                System.out.println(":");
            else
                System.out.println(" for exception " + exception + ":");
            while (idx < length && elements[idx].getClassName().startsWith("org.eclipse.jdt")) {
                StackTraceElement testElement = elements[idx++];
                System.out.println(tab + "   -> " + testElement);
            }
        } else {
            exception.printStackTrace(System.out);
        }
    }

    /**
     * Print given file information with specified indentation.
     * These information are:<ul>
     *    <li>read {@link File#canRead()}</li>
     *    <li>write {@link File#canWrite()}</li>
     *    <li>exists {@link File#exists()}</li>
     *    <li>is file {@link File#isFile()}</li>
     *    <li>is directory {@link File#isDirectory()}</li>
     *    <li>is hidden {@link File#isHidden()}</li>
     * </ul>
     * May recurse several level in parents hierarchy.
     * May also display children, but then will not recusre in parent
     * hierarchy to avoid infinite loop...
     *
     * @param file The file to display information
     * @param indent Number of tab to print before the information
     * @param recurse Display also information on <code>recurse</code>th parents in hierarchy.
     *    If negative then display children information instead.
     */
    private static void printFileInfo(File file, int indent, int recurse) {
        String tab = "";
        for (int i = 0; i < indent; i++)
            tab += "\t";
        System.out.print(tab + "- " + file.getName() + " file info: ");
        String sep = "";
        if (file.canRead()) {
            System.out.print("read");
            sep = ", ";
        }
        if (file.canWrite()) {
            System.out.print(sep + "write");
            sep = ", ";
        }
        if (file.exists()) {
            System.out.print(sep + "exist");
            sep = ", ";
        }
        if (file.isDirectory()) {
            System.out.print(sep + "dir");
            sep = ", ";
        }
        if (file.isFile()) {
            System.out.print(sep + "file");
            sep = ", ";
        }
        if (file.isHidden()) {
            System.out.print(sep + "hidden");
            sep = ", ";
        }
        System.out.println();
        File[] files = file.listFiles();
        int length = files == null ? 0 : files.length;
        if (length > 0) {
            boolean children = recurse < 0;
            System.out.print(tab + "   + children: ");
            if (children)
                System.out.println();
            for (int i = 0; i < length; i++) {
                if (children) { // display children
                    printFileInfo(files[i], indent + 2, -1);
                } else {
                    if (i > 0)
                        System.out.print(", ");
                    System.out.print(files[i].getName());
                    if (files[i].isDirectory())
                        System.out.print("[dir]");
                    else if (files[i].isFile())
                        System.out.print("[file]");
                    else
                        System.out.print("[?]");
                }
            }
            if (!children)
                System.out.println();
        }
        if (recurse > 0) {
            File parent = file.getParentFile();
            if (parent != null)
                printFileInfo(parent, indent + 1, recurse - 1);
        }
    }

    /**
     * Delete a file or directory and insure that the file is no longer present
     * on file system. In case of directory, delete all the hierarchy underneath.
     *
     * @param file The file or directory to delete
     * @return true iff the file was really delete, false otherwise
     */
    public static boolean delete(File file) {
        // flush all directory content
        if (file.isDirectory()) {
            flushDirectoryContent(file);
        }
        // remove file
        file.delete();
        if (isFileDeleted(file)) {
            return true;
        }
        return waitUntilFileDeleted(file);
    }

    /**
     * Returns whether a file is really deleted or not.
     * Does not only rely on {@link File#exists()} method but also
     * look if it's not in its parent children {@link #getParentChildFile(File)}.
     *
     * @param file The file to test if deleted
     * @return true if the file does not exist and was not found in its parent children.
     */
    public static boolean isFileDeleted(File file) {
        return !file.exists() && getParentChildFile(file) == null;
    }

    /**
     * Flush content of a given directory (leaving it empty),
     * no-op if not a directory.
     */
    public static void flushDirectoryContent(File dir) {
        File[] files = dir.listFiles();
        if (files == null)
            return;
        for (int i = 0, max = files.length; i < max; i++) {
            delete(files[i]);
        }
    }

    /**
     * Returns the parent's child file matching the given file or null if not found.
     *
     * @param file The searched file in parent
     * @return The parent's child matching the given file or null if not found.
     */
    private static File getParentChildFile(File file) {
        File parent = file.getParentFile();
        if (parent == null || !parent.exists())
            return null;
        File[] files = parent.listFiles();
        int length = files == null ? 0 : files.length;
        if (length > 0) {
            for (int i = 0; i < length; i++) {
                if (files[i] == file) {
                    return files[i];
                } else if (files[i].equals(file)) {
                    return files[i];
                } else if (files[i].getPath().equals(file.getPath())) {
                    return files[i];
                }
            }
        }
        return null;
    }
}

Related

  1. waitUntilFileDeleted(File file)
  2. waitUntilFileDeleted(File file)
  3. waitUntilFileDeleted(File file)