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     * @author Stephen Colebourne
032     * @version $Id: FileDeleteStrategy.java 723942 2008-12-06 01:24:06Z sebb $
033     * @since Commons IO 1.3
034     */
035    public class FileDeleteStrategy {
036    
037        /**
038         * The singleton instance for normal file deletion, which does not permit
039         * the deletion of directories that are not empty.
040         */
041        public static final FileDeleteStrategy NORMAL = new FileDeleteStrategy("Normal");
042        /**
043         * The singleton instance for forced file deletion, which always deletes,
044         * even if the file represents a non-empty directory.
045         */
046        public static final FileDeleteStrategy FORCE = new ForceFileDeleteStrategy();
047    
048        /** The name of the strategy. */
049        private final String name;
050    
051        //-----------------------------------------------------------------------
052        /**
053         * Restricted constructor.
054         *
055         * @param name  the name by which the strategy is known
056         */
057        protected FileDeleteStrategy(String name) {
058            this.name = name;
059        }
060    
061        //-----------------------------------------------------------------------
062        /**
063         * Deletes the file object, which may be a file or a directory.
064         * All <code>IOException</code>s are caught and false returned instead.
065         * If the file does not exist or is null, true is returned.
066         * <p>
067         * Subclass writers should override {@link #doDelete(File)}, not this method.
068         *
069         * @param fileToDelete  the file to delete, null returns true
070         * @return true if the file was deleted, or there was no such file
071         */
072        public boolean deleteQuietly(File fileToDelete) {
073            if (fileToDelete == null || fileToDelete.exists() == false) {
074                return true;
075            }
076            try {
077                return doDelete(fileToDelete);
078            } catch (IOException ex) {
079                return false;
080            }
081        }
082    
083        /**
084         * Deletes the file object, which may be a file or a directory.
085         * If the file does not exist, the method just returns.
086         * <p>
087         * Subclass writers should override {@link #doDelete(File)}, not this method.
088         *
089         * @param fileToDelete  the file to delete, not null
090         * @throws NullPointerException if the file is null
091         * @throws IOException if an error occurs during file deletion
092         */
093        public void delete(File fileToDelete) throws IOException {
094            if (fileToDelete.exists() && doDelete(fileToDelete) == false) {
095                throw new IOException("Deletion failed: " + fileToDelete);
096            }
097        }
098    
099        /**
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        @Override
126        public String toString() {
127            return "FileDeleteStrategy[" + name + "]";
128        }
129    
130        //-----------------------------------------------------------------------
131        /**
132         * Force file deletion strategy.
133         */
134        static class ForceFileDeleteStrategy extends FileDeleteStrategy {
135            /** Default Constructor */
136            ForceFileDeleteStrategy() {
137                super("Force");
138            }
139    
140            /**
141             * Deletes the file object.
142             * <p>
143             * This implementation uses <code>FileUtils.forceDelete() <code>
144             * if the file exists.
145             *
146             * @param fileToDelete  the file to delete, not null
147             * @return Always returns <code>true</code>
148             * @throws NullPointerException if the file is null
149             * @throws IOException if an error occurs during file deletion
150             */
151            @Override
152            protected boolean doDelete(File fileToDelete) throws IOException {
153                FileUtils.forceDelete(fileToDelete);
154                return true;
155            }
156        }
157    
158    }