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 * https://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 */
17 package org.apache.commons.io;
18
19 import java.io.File;
20 import 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 * <p>
30 * This class captures the strategy to use and is designed for user subclassing.
31 * </p>
32 *
33 * @since 1.3
34 */
35 public class FileDeleteStrategy {
36
37 /**
38 * Force file deletion strategy.
39 */
40 static class ForceFileDeleteStrategy extends FileDeleteStrategy {
41
42 /** Default Constructor */
43 ForceFileDeleteStrategy() {
44 super("Force");
45 }
46
47 /**
48 * Deletes the file object.
49 * <p>
50 * This implementation uses {@code FileUtils.forceDelete()}
51 * if the file exists.
52 * </p>
53 *
54 * @param fileToDelete the file to delete, not null
55 * @return Always returns {@code true}
56 * @throws NullPointerException if the file is null
57 * @throws IOException if an error occurs during file deletion
58 */
59 @Override
60 protected boolean doDelete(final File fileToDelete) throws IOException {
61 FileUtils.forceDelete(fileToDelete);
62 return true;
63 }
64 }
65
66 /**
67 * The singleton instance for normal file deletion, which does not permit
68 * the deletion of directories that are not empty.
69 */
70 public static final FileDeleteStrategy NORMAL = new FileDeleteStrategy("Normal");
71
72 /**
73 * The singleton instance for forced file deletion, which always deletes,
74 * even if the file represents a non-empty directory.
75 */
76 public static final FileDeleteStrategy FORCE = new ForceFileDeleteStrategy();
77
78 /** The name of the strategy. */
79 private final String name;
80
81 /**
82 * Restricted constructor.
83 *
84 * @param name the name by which the strategy is known
85 */
86 protected FileDeleteStrategy(final String name) {
87 this.name = name;
88 }
89
90 /**
91 * Deletes the file object, which may be a file or a directory.
92 * If the file does not exist, the method just returns.
93 * <p>
94 * Subclass writers should override {@link #doDelete(File)}, not this method.
95 * </p>
96 *
97 * @param fileToDelete the file to delete, not null
98 * @throws NullPointerException if the file is null
99 * @throws IOException if an error occurs during file deletion
100 */
101 public void delete(final File fileToDelete) throws IOException {
102 if (fileToDelete.exists() && !doDelete(fileToDelete)) {
103 throw new IOException("Deletion failed: " + fileToDelete);
104 }
105 }
106
107 /**
108 * Deletes the file object, which may be a file or a directory.
109 * All {@link IOException}s are caught and false returned instead.
110 * If the file does not exist or is null, true is returned.
111 * <p>
112 * Subclass writers should override {@link #doDelete(File)}, not this method.
113 * </p>
114 *
115 * @param fileToDelete the file to delete, null returns true
116 * @return true if the file was deleted, or there was no such file
117 */
118 public boolean deleteQuietly(final File fileToDelete) {
119 if (fileToDelete == null || !fileToDelete.exists()) {
120 return true;
121 }
122 try {
123 return doDelete(fileToDelete);
124 } catch (final IOException ex) {
125 return false;
126 }
127 }
128
129 /**
130 * Actually deletes the file object, which may be a file or a directory.
131 * <p>
132 * This method is designed for subclasses to override.
133 * The implementation may return either false or an {@link IOException}
134 * when deletion fails. The {@link #delete(File)} and {@link #deleteQuietly(File)}
135 * methods will handle either response appropriately.
136 * A check has been made to ensure that the file will exist.
137 * </p>
138 * <p>
139 * This implementation uses {@link FileUtils#delete(File)}.
140 * </p>
141 *
142 * @param file the file to delete, exists, not null
143 * @return true if the file was deleted
144 * @throws NullPointerException if the file is null
145 * @throws IOException if an error occurs during file deletion
146 */
147 protected boolean doDelete(final File file) throws IOException {
148 FileUtils.delete(file);
149 return true;
150 }
151
152 /**
153 * Gets a string describing the delete strategy.
154 *
155 * @return a string describing the delete strategy
156 */
157 @Override
158 public String toString() {
159 return "FileDeleteStrategy[" + name + "]";
160 }
161
162 }