1/*
2 * Licensed to the Apache Software Foundation (ASF) under one or more
3 * contributor license agreements.  See the NOTICE file distributed with
4 * this work for additional information regarding copyright ownership.
5 * The ASF licenses this file to You under the Apache License, Version 2.0
6 * (the "License"); you may not use this file except in compliance with
7 * the License.  You may obtain a copy of the License at
8 *
9 *      http://www.apache.org/licenses/LICENSE-2.0
10 *
11 * Unless required by applicable law or agreed to in writing, software
12 * distributed under the License is distributed on an "AS IS" BASIS,
13 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 * See the License for the specific language governing permissions and
15 * limitations under the License.
16 */
17package org.apache.commons.io;
18
19import java.io.File;
20import java.io.IOException;
21
22/**
23 * Strategy for deleting files.
24 * <p>
25 * There is more than one way to delete a file.
26 * You may want to limit access to certain directories, to only delete
27 * directories if they are empty, or maybe to force deletion.
28 * <p>
29 * This class captures the strategy to use and is designed for user subclassing.
30 *
31 * @author Stephen Colebourne
32 * @version $Id: FileDeleteStrategy.java 453903 2006-10-07 13:47:06Z scolebourne $
33 * @since Commons IO 1.3
34 */
35public class FileDeleteStrategy {
36
37    /**
38     * The singleton instance for normal file deletion, which does not permit
39     * the deletion of directories that are not empty.
40     */
41    public static final FileDeleteStrategy NORMAL = new FileDeleteStrategy("Normal");
42    /**
43     * The singleton instance for forced file deletion, which always deletes,
44     * even if the file represents a non-empty directory.
45     */
46    public static final FileDeleteStrategy FORCE = new ForceFileDeleteStrategy();
47
48    /** The name of the strategy. */
49    private final String name;
50
51    //-----------------------------------------------------------------------
52    /**
53     * Restricted constructor.
54     *
55     * @param name  the name by which the strategy is known
56     */
57    protected FileDeleteStrategy(String name) {
58        this.name = name;
59    }
60
61    //-----------------------------------------------------------------------
62    /**
63     * Deletes the file object, which may be a file or a directory.
64     * All <code>IOException</code>s are caught and false returned instead.
65     * If the file does not exist or is null, true is returned.
66     * <p>
67     * Subclass writers should override {@link #doDelete(File)}, not this method.
68     *
69     * @param fileToDelete  the file to delete, null returns true
70     * @return true if the file was deleted, or there was no such file
71     */
72    public boolean deleteQuietly(File fileToDelete) {
73        if (fileToDelete == null || fileToDelete.exists() == false) {
74            return true;
75        }
76        try {
77            return doDelete(fileToDelete);
78        } catch (IOException ex) {
79            return false;
80        }
81    }
82
83    /**
84     * Deletes the file object, which may be a file or a directory.
85     * If the file does not exist, the method just returns.
86     * <p>
87     * Subclass writers should override {@link #doDelete(File)}, not this method.
88     *
89     * @param fileToDelete  the file to delete, not null
90     * @throws NullPointerException if the file is null
91     * @throws IOException if an error occurs during file deletion
92     */
93    public void delete(File fileToDelete) throws IOException {
94        if (fileToDelete.exists() && doDelete(fileToDelete) == false) {
95            throw new IOException("Deletion failed: " + fileToDelete);
96        }
97    }
98
99    /**
100     * Actually deletes the file object, which may be a file or a directory.
101     * <p>
102     * This method is designed for subclasses to override.
103     * The implementation may return either false or an <code>IOException</code>
104     * when deletion fails. The {@link #delete(File)} and {@link #deleteQuietly(File)}
105     * methods will handle either response appropriately.
106     * A check has been made to ensure that the file will exist.
107     * <p>
108     * This implementation uses {@link File#delete()}.
109     *
110     * @param fileToDelete  the file to delete, exists, not null
111     * @return true if the file was deleteds
112     * @throws NullPointerException if the file is null
113     * @throws IOException if an error occurs during file deletion
114     */
115    protected boolean doDelete(File fileToDelete) throws IOException {
116        return fileToDelete.delete();
117    }
118
119    //-----------------------------------------------------------------------
120    /**
121     * Gets a string describing the delete strategy.
122     *
123     * @return a string describing the delete strategy
124     */
125    public String toString() {
126        return "FileDeleteStrategy[" + name + "]";
127    }
128
129    //-----------------------------------------------------------------------
130    /**
131     * Force file deletion strategy.
132     */
133    static class ForceFileDeleteStrategy extends FileDeleteStrategy {
134        /** Default Constructor */
135        ForceFileDeleteStrategy() {
136            super("Force");
137        }
138
139        /**
140         * Deletes the file object.
141         * <p>
142         * This implementation uses <code>FileUtils.forceDelete() <code>
143         * if the file exists.
144         *
145         * @param fileToDelete  the file to delete, not null
146         * @return Always returns <code>true</code>
147         * @throws NullPointerException if the file is null
148         * @throws IOException if an error occurs during file deletion
149         */
150        protected boolean doDelete(File fileToDelete) throws IOException {
151            FileUtils.forceDelete(fileToDelete);
152            return true;
153        }
154    }
155
156}
157