    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    }