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.Objects; 026 027import org.apache.commons.io.file.Counters.PathCounters; 028import org.apache.commons.io.filefilter.TrueFileFilter; 029 030/** 031 * Counts files, directories, and sizes, as a visit proceeds. 032 * 033 * @since 2.7 034 */ 035public class CountingPathVisitor extends SimplePathVisitor { 036 037 static final String[] EMPTY_STRING_ARRAY = {}; 038 039 /** 040 * Creates a new instance configured with a BigInteger {@link PathCounters}. 041 * 042 * @return a new instance configured with a BigInteger {@link PathCounters}. 043 */ 044 public static CountingPathVisitor withBigIntegerCounters() { 045 return new CountingPathVisitor(Counters.bigIntegerPathCounters()); 046 } 047 048 /** 049 * Creates a new instance configured with a long {@link PathCounters}. 050 * 051 * @return a new instance configured with a long {@link PathCounters}. 052 */ 053 public static CountingPathVisitor withLongCounters() { 054 return new CountingPathVisitor(Counters.longPathCounters()); 055 } 056 057 private final PathCounters pathCounters; 058 private final PathFilter fileFilter; 059 private final PathFilter dirFilter; 060 061 /** 062 * Constructs a new instance. 063 * 064 * @param pathCounter How to count path visits. 065 */ 066 public CountingPathVisitor(final PathCounters pathCounter) { 067 this(pathCounter, TrueFileFilter.INSTANCE, TrueFileFilter.INSTANCE); 068 } 069 070 /** 071 * Constructs a new instance. 072 * 073 * @param pathCounter How to count path visits. 074 * @param fileFilter Filters which files to count. 075 * @param dirFilter Filters which directories to count. 076 * @since 2.9.0 077 */ 078 public CountingPathVisitor(final PathCounters pathCounter, final PathFilter fileFilter, final PathFilter dirFilter) { 079 this.pathCounters = Objects.requireNonNull(pathCounter, "pathCounter"); 080 this.fileFilter = Objects.requireNonNull(fileFilter, "fileFilter"); 081 this.dirFilter = Objects.requireNonNull(dirFilter, "dirFilter"); 082 } 083 084 @Override 085 public boolean equals(final Object obj) { 086 if (this == obj) { 087 return true; 088 } 089 if (!(obj instanceof CountingPathVisitor)) { 090 return false; 091 } 092 final CountingPathVisitor other = (CountingPathVisitor) obj; 093 return Objects.equals(pathCounters, other.pathCounters); 094 } 095 096 /** 097 * Gets the visitation counts. 098 * 099 * @return the visitation counts. 100 */ 101 public PathCounters getPathCounters() { 102 return pathCounters; 103 } 104 105 @Override 106 public int hashCode() { 107 return Objects.hash(pathCounters); 108 } 109 110 @Override 111 public FileVisitResult postVisitDirectory(final Path dir, final IOException exc) throws IOException { 112 updateDirCounter(dir, exc); 113 return FileVisitResult.CONTINUE; 114 } 115 116 @Override 117 public FileVisitResult preVisitDirectory(final Path dir, final BasicFileAttributes attributes) throws IOException { 118 final FileVisitResult accept = dirFilter.accept(dir, attributes); 119 return accept != FileVisitResult.CONTINUE ? FileVisitResult.SKIP_SUBTREE : FileVisitResult.CONTINUE; 120 } 121 122 @Override 123 public String toString() { 124 return pathCounters.toString(); 125 } 126 127 /** 128 * Updates the counter for visiting the given directory. 129 * 130 * @param dir the visited directory. 131 * @param exc Encountered exception. 132 * @since 2.9.0 133 */ 134 protected void updateDirCounter(final Path dir, final IOException exc) { 135 pathCounters.getDirectoryCounter().increment(); 136 } 137 138 /** 139 * Updates the counters for visiting the given file. 140 * 141 * @param file the visited file. 142 * @param attributes the visited file attributes. 143 */ 144 protected void updateFileCounters(final Path file, final BasicFileAttributes attributes) { 145 pathCounters.getFileCounter().increment(); 146 pathCounters.getByteCounter().add(attributes.size()); 147 } 148 149 @Override 150 public FileVisitResult visitFile(final Path file, final BasicFileAttributes attributes) throws IOException { 151 if (Files.exists(file) && fileFilter.accept(file, attributes) == FileVisitResult.CONTINUE) { 152 updateFileCounters(file, attributes); 153 } 154 return FileVisitResult.CONTINUE; 155 } 156 157}