1 /* 2 * Licensed to the Apache Software Foundation (ASF) under one or more 3 * contributor license agreements. See the NOTICE file distributed with 4 * this work for additional information regarding copyright ownership. 5 * The ASF licenses this file to You under the Apache License, Version 2.0 6 * (the "License"); you may not use this file except in compliance with 7 * the License. You may obtain a copy of the License at 8 * 9 * http://www.apache.org/licenses/LICENSE-2.0 10 * 11 * Unless required by applicable law or agreed to in writing, software 12 * distributed under the License is distributed on an "AS IS" BASIS, 13 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 * See the License for the specific language governing permissions and 15 * limitations under the License. 16 */ 17 package org.apache.commons.io.filefilter; 18 19 import java.io.File; 20 import java.io.Serializable; 21 import java.nio.file.FileVisitResult; 22 import java.nio.file.Path; 23 import java.nio.file.attribute.BasicFileAttributes; 24 import java.util.List; 25 import java.util.Objects; 26 import java.util.stream.Stream; 27 28 import org.apache.commons.io.IOCase; 29 import org.apache.commons.io.file.PathUtils; 30 31 /** 32 * Filters files based on the suffix (what the file name ends with). 33 * This is used in retrieving all the files of a particular type. 34 * <p> 35 * For example, to retrieve and print all {@code *.java} files 36 * in the current directory: 37 * </p> 38 * <h2>Using Classic IO</h2> 39 * <pre> 40 * File dir = FileUtils.current(); 41 * String[] files = dir.list(new SuffixFileFilter(".java")); 42 * for (String file : files) { 43 * System.out.println(file); 44 * } 45 * </pre> 46 * 47 * <h2>Using NIO</h2> 48 * <pre> 49 * final Path dir = PathUtils.current(); 50 * final AccumulatorPathVisitor visitor = AccumulatorPathVisitor.withLongCounters(new SuffixFileFilter(".java")); 51 * // 52 * // Walk one dir 53 * Files.<b>walkFileTree</b>(dir, Collections.emptySet(), 1, visitor); 54 * System.out.println(visitor.getPathCounters()); 55 * System.out.println(visitor.getFileList()); 56 * // 57 * visitor.getPathCounters().reset(); 58 * // 59 * // Walk dir tree 60 * Files.<b>walkFileTree</b>(dir, visitor); 61 * System.out.println(visitor.getPathCounters()); 62 * System.out.println(visitor.getDirList()); 63 * System.out.println(visitor.getFileList()); 64 * </pre> 65 * <h2>Deprecating Serialization</h2> 66 * <p> 67 * <em>Serialization is deprecated and will be removed in 3.0.</em> 68 * </p> 69 * 70 * @since 1.0 71 * @see FileFilterUtils#suffixFileFilter(String) 72 * @see FileFilterUtils#suffixFileFilter(String, IOCase) 73 */ 74 public class SuffixFileFilter extends AbstractFileFilter implements Serializable { 75 76 private static final long serialVersionUID = -3389157631240246157L; 77 78 /** The file name suffixes to search for */ 79 private final String[] suffixes; 80 81 /** Whether the comparison is case-sensitive. */ 82 private final IOCase ioCase; 83 84 /** 85 * Constructs a new Suffix file filter for a list of suffixes. 86 * 87 * @param suffixes the suffixes to allow, must not be null 88 * @throws IllegalArgumentException if the suffix list is null 89 * @throws ClassCastException if the list does not contain Strings 90 */ 91 public SuffixFileFilter(final List<String> suffixes) { 92 this(suffixes, IOCase.SENSITIVE); 93 } 94 95 /** 96 * Constructs a new Suffix file filter for a list of suffixes 97 * specifying case-sensitivity. 98 * 99 * @param suffixes the suffixes to allow, must not be null 100 * @param ioCase how to handle case sensitivity, null means case-sensitive 101 * @throws IllegalArgumentException if the suffix list is null 102 * @throws ClassCastException if the list does not contain Strings 103 * @since 1.4 104 */ 105 public SuffixFileFilter(final List<String> suffixes, final IOCase ioCase) { 106 Objects.requireNonNull(suffixes, "suffixes"); 107 this.suffixes = suffixes.toArray(EMPTY_STRING_ARRAY); 108 this.ioCase = IOCase.value(ioCase, IOCase.SENSITIVE); 109 } 110 111 /** 112 * Constructs a new Suffix file filter for a single extension. 113 * 114 * @param suffix the suffix to allow, must not be null 115 * @throws IllegalArgumentException if the suffix is null 116 */ 117 public SuffixFileFilter(final String suffix) { 118 this(suffix, IOCase.SENSITIVE); 119 } 120 121 /** 122 * Constructs a new Suffix file filter for an array of suffixes. 123 * <p> 124 * The array is not cloned, so could be changed after constructing the 125 * instance. This would be inadvisable however. 126 * 127 * @param suffixes the suffixes to allow, must not be null 128 * @throws NullPointerException if the suffix array is null 129 */ 130 public SuffixFileFilter(final String... suffixes) { 131 this(suffixes, IOCase.SENSITIVE); 132 } 133 134 /** 135 * Constructs a new Suffix file filter for a single extension 136 * specifying case-sensitivity. 137 * 138 * @param suffix the suffix to allow, must not be null 139 * @param ioCase how to handle case sensitivity, null means case-sensitive 140 * @throws NullPointerException if the suffix is null 141 * @since 1.4 142 */ 143 public SuffixFileFilter(final String suffix, final IOCase ioCase) { 144 Objects.requireNonNull(suffix, "suffix"); 145 this.suffixes = new String[] {suffix}; 146 this.ioCase = IOCase.value(ioCase, IOCase.SENSITIVE); 147 } 148 149 /** 150 * Constructs a new Suffix file filter for an array of suffixes 151 * specifying case-sensitivity. 152 * 153 * @param suffixes the suffixes to allow, must not be null 154 * @param ioCase how to handle case sensitivity, null means case-sensitive 155 * @throws NullPointerException if the suffix array is null 156 * @since 1.4 157 */ 158 public SuffixFileFilter(final String[] suffixes, final IOCase ioCase) { 159 Objects.requireNonNull(suffixes, "suffixes"); 160 this.suffixes = suffixes.clone(); 161 this.ioCase = IOCase.value(ioCase, IOCase.SENSITIVE); 162 } 163 164 /** 165 * Checks to see if the file name ends with the suffix. 166 * 167 * @param file the File to check 168 * @return true if the file name ends with one of our suffixes 169 */ 170 @Override 171 public boolean accept(final File file) { 172 return accept(file.getName()); 173 } 174 175 /** 176 * Checks to see if the file name ends with the suffix. 177 * 178 * @param file the File directory 179 * @param name the file name 180 * @return true if the file name ends with one of our suffixes 181 */ 182 @Override 183 public boolean accept(final File file, final String name) { 184 return accept(name); 185 } 186 187 /** 188 * Checks to see if the file name ends with the suffix. 189 * @param path the File to check 190 * 191 * @return true if the file name ends with one of our suffixes 192 * @since 2.9.0 193 */ 194 @Override 195 public FileVisitResult accept(final Path path, final BasicFileAttributes attributes) { 196 return toFileVisitResult(accept(PathUtils.getFileNameString(path))); 197 } 198 199 private boolean accept(final String name) { 200 return Stream.of(suffixes).anyMatch(suffix -> ioCase.checkEndsWith(name, suffix)); 201 } 202 203 /** 204 * Provide a String representation of this file filter. 205 * 206 * @return a String representation 207 */ 208 @Override 209 public String toString() { 210 final StringBuilder buffer = new StringBuilder(); 211 buffer.append(super.toString()); 212 buffer.append("("); 213 append(suffixes, buffer); 214 buffer.append(")"); 215 return buffer.toString(); 216 } 217 218 }