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 018package org.apache.commons.io.file; 019 020import java.io.IOException; 021import java.nio.file.FileVisitResult; 022import java.nio.file.Files; 023import java.nio.file.Path; 024import java.nio.file.attribute.BasicFileAttributes; 025import java.util.Arrays; 026import java.util.Objects; 027 028import org.apache.commons.io.file.Counters.PathCounters; 029 030/** 031 * Deletes files and directories as a visit proceeds. 032 * 033 * @since 2.7 034 */ 035public class DeletingPathVisitor extends CountingPathVisitor { 036 037 038 /** 039 * Creates a new instance configured with a BigInteger {@link PathCounters}. 040 * 041 * @return a new instance configured with a BigInteger {@link PathCounters}. 042 */ 043 public static DeletingPathVisitor withBigIntegerCounters() { 044 return new DeletingPathVisitor(Counters.bigIntegerPathCounters()); 045 } 046 047 /** 048 * Creates a new instance configured with a long {@link PathCounters}. 049 * 050 * @return a new instance configured with a long {@link PathCounters}. 051 */ 052 public static DeletingPathVisitor withLongCounters() { 053 return new DeletingPathVisitor(Counters.longPathCounters()); 054 } 055 056 private final String[] skip; 057 058 /** 059 * Constructs a new visitor that deletes files except for the files and directories explicitly given. 060 * 061 * @param pathCounter How to count visits. 062 * 063 * @param skip The files to skip deleting. 064 */ 065 public DeletingPathVisitor(final PathCounters pathCounter, final String... skip) { 066 super(pathCounter); 067 final String[] temp = skip != null ? skip.clone() : EMPTY_STRING_ARRAY; 068 Arrays.sort(temp); 069 this.skip = temp; 070 } 071 072 /** 073 * Returns true to process the given path, false if not. 074 * 075 * @param path the path to test. 076 * @return true to process the given path, false if not. 077 */ 078 private boolean accept(final Path path) { 079 return Arrays.binarySearch(skip, Objects.toString(path.getFileName(), null)) < 0; 080 } 081 082 @Override 083 public FileVisitResult postVisitDirectory(final Path dir, final IOException exc) throws IOException { 084 if (PathUtils.isEmptyDirectory(dir)) { 085 Files.deleteIfExists(dir); 086 } 087 return super.postVisitDirectory(dir, exc); 088 } 089 090 @Override 091 public FileVisitResult preVisitDirectory(final Path dir, final BasicFileAttributes attrs) throws IOException { 092 super.preVisitDirectory(dir, attrs); 093 return accept(dir) ? FileVisitResult.CONTINUE : FileVisitResult.SKIP_SUBTREE; 094 } 095 096 @Override 097 public FileVisitResult visitFile(final Path file, final BasicFileAttributes attrs) throws IOException { 098 if (accept(file) && Files.exists(file)) { 099 Files.deleteIfExists(file); 100 } 101 updateFileCounters(file, attrs); 102 return FileVisitResult.CONTINUE; 103 } 104}