001    /*
002     * Licensed to the Apache Software Foundation (ASF) under one or more
003     * contributor license agreements.  See the NOTICE file distributed with
004     * this work for additional information regarding copyright ownership.
005     * The ASF licenses this file to You under the Apache License, Version 2.0
006     * (the "License"); you may not use this file except in compliance with
007     * the License.  You may obtain a copy of the License at
008     * 
009     *      http://www.apache.org/licenses/LICENSE-2.0
010     * 
011     * Unless required by applicable law or agreed to in writing, software
012     * distributed under the License is distributed on an "AS IS" BASIS,
013     * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
014     * See the License for the specific language governing permissions and
015     * limitations under the License.
016     */
017    package org.apache.commons.io;
018    
019    import java.io.File;
020    import java.io.IOException;
021    
022    /**
023     * Strategy for deleting files.
024     * <p>
025     * There is more than one way to delete a file.
026     * You may want to limit access to certain directories, to only delete
027     * directories if they are empty, or maybe to force deletion.
028     * <p>
029     * This class captures the strategy to use and is designed for user subclassing.
030     *
031     * @version $Id: FileDeleteStrategy.java 1307461 2012-03-30 15:12:29Z ggregory $
032     * @since 1.3
033     */
034    public class FileDeleteStrategy {
035    
036        /**
037         * The singleton instance for normal file deletion, which does not permit
038         * the deletion of directories that are not empty.
039         */
040        public static final FileDeleteStrategy NORMAL = new FileDeleteStrategy("Normal");
041        /**
042         * The singleton instance for forced file deletion, which always deletes,
043         * even if the file represents a non-empty directory.
044         */
045        public static final FileDeleteStrategy FORCE = new ForceFileDeleteStrategy();
046    
047        /** The name of the strategy. */
048        private final String name;
049    
050        //-----------------------------------------------------------------------
051        /**
052         * Restricted constructor.
053         *
054         * @param name  the name by which the strategy is known
055         */
056        protected FileDeleteStrategy(String name) {
057            this.name = name;
058        }
059    
060        //-----------------------------------------------------------------------
061        /**
062         * Deletes the file object, which may be a file or a directory.
063         * All <code>IOException</code>s are caught and false returned instead.
064         * If the file does not exist or is null, true is returned.
065         * <p>
066         * Subclass writers should override {@link #doDelete(File)}, not this method.
067         *
068         * @param fileToDelete  the file to delete, null returns true
069         * @return true if the file was deleted, or there was no such file
070         */
071        public boolean deleteQuietly(File fileToDelete) {
072            if (fileToDelete == null || fileToDelete.exists() == false) {
073                return true;
074            }
075            try {
076                return doDelete(fileToDelete);
077            } catch (IOException ex) {
078                return false;
079            }
080        }
081    
082        /**
083         * Deletes the file object, which may be a file or a directory.
084         * If the file does not exist, the method just returns.
085         * <p>
086         * Subclass writers should override {@link #doDelete(File)}, not this method.
087         *
088         * @param fileToDelete  the file to delete, not null
089         * @throws NullPointerException if the file is null
090         * @throws IOException if an error occurs during file deletion
091         */
092        public void delete(File fileToDelete) throws IOException {
093            if (fileToDelete.exists() && doDelete(fileToDelete) == false) {
094                throw new IOException("Deletion failed: " + fileToDelete);
095            }
096        }
097    
098        /**
099         * Actually deletes the file object, which may be a file or a directory.
100         * <p>
101         * This method is designed for subclasses to override.
102         * The implementation may return either false or an <code>IOException</code>
103         * when deletion fails. The {@link #delete(File)} and {@link #deleteQuietly(File)}
104         * methods will handle either response appropriately.
105         * A check has been made to ensure that the file will exist.
106         * <p>
107         * This implementation uses {@link File#delete()}.
108         *
109         * @param fileToDelete  the file to delete, exists, not null
110         * @return true if the file was deleteds
111         * @throws NullPointerException if the file is null
112         * @throws IOException if an error occurs during file deletion
113         */
114        protected boolean doDelete(File fileToDelete) throws IOException {
115            return fileToDelete.delete();
116        }
117    
118        //-----------------------------------------------------------------------
119        /**
120         * Gets a string describing the delete strategy.
121         *
122         * @return a string describing the delete strategy
123         */
124        @Override
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}
147             * @throws NullPointerException if the file is null
148             * @throws IOException if an error occurs during file deletion
149             */
150            @Override
151            protected boolean doDelete(File fileToDelete) throws IOException {
152                FileUtils.forceDelete(fileToDelete);
153                return true;
154            }
155        }
156    
157    }