class TempFileDeleter {

    private final ReferenceQueue<Object> queue = new ReferenceQueue<Object>();
    private final HashMap<PhantomReference<?>, String> refMap = new HashMap<>();

    private TempFileDeleter() {
        // utility class
    }

    public static TempFileDeleter getInstance() {
        return new TempFileDeleter();
    }

    /**
     * Add a file to the list of temp files to delete. The file is deleted once
     * the file object is garbage collected.
     *
     * @param fileName the file name
     * @param file the object to monitor
     * @return the reference that can be used to stop deleting the file
     */
    public synchronized Reference<?> addFile(String fileName, Object file) {
        IOUtils.trace("TempFileDeleter.addFile", fileName, file);
        PhantomReference<?> ref = new PhantomReference<Object>(file, queue);
        refMap.put(ref, fileName);
        deleteUnused();
        return ref;
    }

    /**
     * Delete the given file now. This will remove the reference from the list.
     *
     * @param ref the reference as returned by addFile
     * @param fileName the file name
     */
    public synchronized void deleteFile(Reference<?> ref, String fileName) {
        if (ref != null) {
            String f2 = refMap.remove(ref);
            if (f2 != null) {
                if (SysProperties.CHECK) {
                    if (fileName != null && !f2.equals(fileName)) {
                        DbException.throwInternalError("f2:" + f2 + " f:" + fileName);
                    }
                }
                fileName = f2;
            }
        }
        if (fileName != null && FileUtils.exists(fileName)) {
            try {
                IOUtils.trace("TempFileDeleter.deleteFile", fileName, null);
                FileUtils.tryDelete(fileName);
            } catch (Exception e) {
                // TODO log such errors?
            }
        }
    }

    /**
     * Delete all registered temp files.
     */
    public void deleteAll() {
        for (String tempFile : new ArrayList<>(refMap.values())) {
            deleteFile(null, tempFile);
        }
        deleteUnused();
    }

    /**
     * Delete all unused files now.
     */
    public void deleteUnused() {<FILL_FUNCTION_BODY>}

    /**
     * This method is called if a file should no longer be deleted if the object
     * is garbage collected.
     *
     * @param ref the reference as returned by addFile
     * @param fileName the file name
     */
    public void stopAutoDelete(Reference<?> ref, String fileName) {
        IOUtils.trace("TempFileDeleter.stopAutoDelete", fileName, ref);
        if (ref != null) {
            String f2 = refMap.remove(ref);
            if (SysProperties.CHECK) {
                if (f2 == null || !f2.equals(fileName)) {
                    DbException.throwInternalError(
                            "f2:" + f2 + " " + (f2 == null ? "" : f2) + " f:" + fileName);
                }
            }
        }
        deleteUnused();
    }

}

        while (queue != null) {
            Reference<? extends Object> ref = queue.poll();
            if (ref == null) {
                break;
            }
            deleteFile(ref, null);
        }
    
<no_super_class>