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;
//License from project: Open Source License 

import java.io.File;
import org.eclipse.core.resources.IContainer;
import org.eclipse.core.resources.IResource;
import org.eclipse.core.runtime.CoreException;

public class Main {
    private static int DELETE_MAX_TIME = 0;
    /**/*from   ww  w . jav  a2 s  . c om*/
     * Trace deletion operations while running RDT/Core tests.
     */
    public static boolean DELETE_DEBUG = false;
    /**
     * Maximum of time in ms to wait in deletion operation while running RDT/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);
            printRdtCoreStackTrace(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);
            printRdtCoreStackTrace(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.rubypeoplee.rdt")) {
            // loop until RDT/Core class appears in the stack
        }
        if (idx < length) {
            StackTraceElement testElement = null;
            while (idx < length && elements[idx].getClassName().startsWith("org.rubypeople.rdt")) {
                testElement = elements[idx++];
            }
            if (testElement != null) {
                return testElement.getClassName() + " - " + testElement.getMethodName();
            }
        }
        return "?";
    }

    /**
     * Print stack trace with only RDT/Core 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 printRdtCoreStackTrace(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.rubypeople.rdt")) {
            // 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.rubypeople.rdt")) {
                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 resource The resource to delete
     * @return true iff the file was really delete, false otherwise
     */
    public static boolean delete(IResource resource) {
        try {
            resource.delete(true, null);
            if (isResourceDeleted(resource)) {
                return true;
            }
        } catch (CoreException e) {
            //   skip
        }
        return waitUntilResourceDeleted(resource);
    }

    /**
     * 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;
    }

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

    /**
     * Wait until a resource is _really_ deleted on file system.
     * 
     * @param resource Deleted resource
     * @return true if the file was finally deleted, false otherwise
     */
    private static boolean waitUntilResourceDeleted(IResource resource) {
        File file = resource.getLocation().toFile();
        if (DELETE_DEBUG) {
            System.out.println();
            System.out.println("WARNING in test: " + getTestName());
            System.out.println("   - problems occured while deleting resource " + resource);
            printRdtCoreStackTrace(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 (resource.isAccessible()) {
                    try {
                        resource.delete(true, null);
                        if (isResourceDeleted(resource) && isFileDeleted(file)) {
                            // SUCCESS
                            if (DELETE_DEBUG) {
                                System.out.println();
                                System.out.println("   => resource really removed after " + time + "ms (max="
                                        + DELETE_MAX_TIME + "ms)");
                                System.out.println();
                            }
                            return true;
                        }
                    } catch (CoreException e) {
                        //   skip
                    }
                }
                if (isResourceDeleted(resource) && isFileDeleted(file)) {
                    // SUCCESS
                    if (DELETE_DEBUG) {
                        System.out.println();
                        System.out.println(
                                "   => resource 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 resource " + resource);
            printRdtCoreStackTrace(null, 1);
            printFileInfo(file.getParentFile(), 1, -1); // display parent with its children
        }
        System.out.println();
        System.out.println("   !!! ERROR: " + resource + " was never deleted even after having waited "
                + DELETE_MAX_TIME + "ms!!!");
        System.out.println();
        return false;
    }

    /**
     * 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]);
        }
    }

    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;
    }

    /**
     * Returns parent's child resource matching the given resource or null if not found.
     * 
     * @param resource The searched file in parent
     * @return The parent's child matching the given file or null if not found.
     */
    private static IResource getParentChildResource(IResource resource) {
        IContainer parent = resource.getParent();
        if (parent == null || !parent.exists())
            return null;
        try {
            IResource[] members = parent.members();
            int length = members == null ? 0 : members.length;
            if (length > 0) {
                for (int i = 0; i < length; i++) {
                    if (members[i] == resource) {
                        return members[i];
                    } else if (members[i].equals(resource)) {
                        return members[i];
                    } else if (members[i].getFullPath().equals(resource.getFullPath())) {
                        return members[i];
                    }
                }
            }
        } catch (CoreException ce) {
            // skip
        }
        return null;
    }
}

Related

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