View Javadoc
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   */
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 }