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    *      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.function.Function;
25  import java.util.regex.Pattern;
26  
27  import org.apache.commons.io.IOCase;
28  
29  /**
30   * Filters files using supplied regular expression(s).
31   * <p>
32   * See java.util.regex.Pattern for regex matching rules.
33   * </p>
34   * <h2>Using Classic IO</h2>
35   * <p>
36   * e.g.
37   *
38   * <pre>
39   * File dir = new File(".");
40   * FileFilter fileFilter = new RegexFileFilter("^.*[tT]est(-\\d+)?\\.java$");
41   * File[] files = dir.listFiles(fileFilter);
42   * for (String file : files) {
43   *     System.out.println(file);
44   * }
45   * </pre>
46   *
47   * <h2>Using NIO</h2>
48   *
49   * <pre>
50   * final Path dir = Paths.get("");
51   * final AccumulatorPathVisitor visitor = AccumulatorPathVisitor.withLongCounters(new RegexFileFilter("^.*[tT]est(-\\d+)?\\.java$"));
52   * //
53   * // Walk one dir
54   * Files.<b>walkFileTree</b>(dir, Collections.emptySet(), 1, visitor);
55   * System.out.println(visitor.getPathCounters());
56   * System.out.println(visitor.getFileList());
57   * //
58   * visitor.getPathCounters().reset();
59   * //
60   * // Walk dir tree
61   * Files.<b>walkFileTree</b>(dir, visitor);
62   * System.out.println(visitor.getPathCounters());
63   * System.out.println(visitor.getDirList());
64   * System.out.println(visitor.getFileList());
65   * </pre>
66   *
67   * @since 1.4
68   */
69  public class RegexFileFilter extends AbstractFileFilter implements Serializable {
70  
71      private static final long serialVersionUID = 4269646126155225062L;
72  
73      /**
74       * Compiles the given pattern source.
75       *
76       * @param pattern the source pattern.
77       * @param flags the compilation flags.
78       * @return a new Pattern.
79       */
80      private static Pattern compile(final String pattern, final int flags) {
81          if (pattern == null) {
82              throw new IllegalArgumentException("Pattern is missing");
83          }
84          return Pattern.compile(pattern, flags);
85      }
86  
87      /**
88       * Converts IOCase to Pattern compilation flags.
89       *
90       * @param caseSensitivity case-sensitivity.
91       * @return Pattern compilation flags.
92       */
93      private static int toFlags(final IOCase caseSensitivity) {
94          return IOCase.isCaseSensitive(caseSensitivity) ? Pattern.CASE_INSENSITIVE : 0;
95      }
96  
97      /** The regular expression pattern that will be used to match file names. */
98      private final Pattern pattern;
99      
100     /** How convert a path to a string. */
101     private final Function<Path, String> pathToString;
102 
103     /**
104      * Constructs a new regular expression filter for a compiled regular expression
105      *
106      * @param pattern regular expression to match.
107      * @throws IllegalArgumentException if the pattern is null.
108      */
109     public RegexFileFilter(final Pattern pattern) {
110         this(pattern, p -> p.getFileName().toString());
111     }
112 
113     /**
114      * Constructs a new regular expression filter for a compiled regular expression
115      *
116      * @param pattern regular expression to match.
117      * @param pathToString How convert a path to a string.
118      * @throws IllegalArgumentException if the pattern is null.
119      * @since 2.10.0
120      */
121     public RegexFileFilter(final Pattern pattern, final Function<Path, String> pathToString) {
122         if (pattern == null) {
123             throw new IllegalArgumentException("Pattern is missing");
124         }
125         this.pattern = pattern;
126         this.pathToString = pathToString;
127     }
128 
129     /**
130      * Constructs a new regular expression filter.
131      *
132      * @param pattern regular string expression to match
133      * @throws IllegalArgumentException if the pattern is null
134      */
135     public RegexFileFilter(final String pattern) {
136         this(pattern, 0);
137     }
138 
139     /**
140      * Constructs a new regular expression filter with the specified flags.
141      *
142      * @param pattern regular string expression to match
143      * @param flags pattern flags - e.g. {@link Pattern#CASE_INSENSITIVE}
144      * @throws IllegalArgumentException if the pattern is null
145      */
146     public RegexFileFilter(final String pattern, final int flags) {
147         this(compile(pattern, flags));
148     }
149 
150     /**
151      * Constructs a new regular expression filter with the specified flags case sensitivity.
152      *
153      * @param pattern regular string expression to match
154      * @param caseSensitivity how to handle case sensitivity, null means case-sensitive
155      * @throws IllegalArgumentException if the pattern is null
156      */
157     public RegexFileFilter(final String pattern, final IOCase caseSensitivity) {
158         this(compile(pattern, toFlags(caseSensitivity)));
159     }
160 
161     /**
162      * Checks to see if the file name matches one of the regular expressions.
163      *
164      * @param dir the file directory (ignored)
165      * @param name the file name
166      * @return true if the file name matches one of the regular expressions
167      */
168     @Override
169     public boolean accept(final File dir, final String name) {
170         return pattern.matcher(name).matches();
171     }
172 
173     /**
174      * Checks to see if the file name matches one of the regular expressions.
175      *
176      * @param path the path
177      * @param attributes the path attributes
178      * @return true if the file name matches one of the regular expressions
179      */
180     @Override
181     public FileVisitResult accept(final Path path, final BasicFileAttributes attributes) {
182         return toFileVisitResult(pattern.matcher(pathToString.apply(path)).matches(), path);
183     }
184 
185     /**
186      * Returns a debug string.
187      *
188      * @since 2.10.0
189      */
190     @Override
191     public String toString() {
192         return "RegexFileFilter [pattern=" + pattern + "]";
193     }
194 
195 }