View Javadoc
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    *      https://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 directory
53   * Files.<strong>walkFileTree</strong>(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 directory tree
60   * Files.<strong>walkFileTree</strong>(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      * </p>
127      *
128      * @param suffixes  the suffixes to allow, must not be null.
129      * @throws NullPointerException if the suffix array is null.
130      */
131     public SuffixFileFilter(final String... suffixes) {
132         this(suffixes, IOCase.SENSITIVE);
133     }
134 
135     /**
136      * Constructs a new Suffix file filter for a single extension
137      * specifying case-sensitivity.
138      *
139      * @param suffix  the suffix to allow, must not be null.
140      * @param ioCase  how to handle case sensitivity, null means case-sensitive.
141      * @throws NullPointerException if the suffix is null.
142      * @since 1.4
143      */
144     public SuffixFileFilter(final String suffix, final IOCase ioCase) {
145         Objects.requireNonNull(suffix, "suffix");
146         this.suffixes = new String[] {suffix};
147         this.ioCase = IOCase.value(ioCase, IOCase.SENSITIVE);
148     }
149 
150     /**
151      * Constructs a new Suffix file filter for an array of suffixes
152      * specifying case-sensitivity.
153      *
154      * @param suffixes  the suffixes to allow, must not be null.
155      * @param ioCase  how to handle case sensitivity, null means case-sensitive.
156      * @throws NullPointerException if the suffix array is null.
157      * @since 1.4
158      */
159     public SuffixFileFilter(final String[] suffixes, final IOCase ioCase) {
160         Objects.requireNonNull(suffixes, "suffixes");
161         this.suffixes = suffixes.clone();
162         this.ioCase = IOCase.value(ioCase, IOCase.SENSITIVE);
163     }
164 
165     /**
166      * Tests to see if the file name ends with the suffix.
167      *
168      * @param file  the File to check.
169      * @return true if the file name ends with one of our suffixes.
170      */
171     @Override
172     public boolean accept(final File file) {
173         return accept(file.getName());
174     }
175 
176     /**
177      * Tests to see if the file name ends with the suffix.
178      *
179      * @param file  the File directory.
180      * @param name  the file name.
181      * @return true if the file name ends with one of our suffixes.
182      */
183     @Override
184     public boolean accept(final File file, final String name) {
185         return accept(name);
186     }
187 
188     /**
189      * Tests to see if the file name ends with the suffix.
190      *
191      * @param path       the File to check.
192      * @param attributes the path's basic attributes (may be null).
193      * @return true if the file name ends with one of our suffixes.
194      * @since 2.9.0
195      */
196     @Override
197     public FileVisitResult accept(final Path path, final BasicFileAttributes attributes) {
198         return toFileVisitResult(accept(PathUtils.getFileNameString(path)));
199     }
200 
201     private boolean accept(final String name) {
202         return Stream.of(suffixes).anyMatch(suffix -> ioCase.checkEndsWith(name, suffix));
203     }
204 
205     /**
206      * Provides a String representation of this file filter.
207      *
208      * @return a String representation.
209      */
210     @Override
211     public String toString() {
212         final StringBuilder buffer = new StringBuilder();
213         buffer.append(super.toString());
214         buffer.append("(");
215         append(suffixes, buffer);
216         buffer.append(")");
217         return buffer.toString();
218     }
219 
220 }