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 */
017package org.apache.commons.io.filefilter;
018
019import java.io.File;
020import java.io.Serializable;
021import java.nio.file.FileVisitResult;
022import java.nio.file.Files;
023import java.nio.file.Path;
024import java.nio.file.attribute.BasicFileAttributes;
025import java.util.List;
026import java.util.Objects;
027import java.util.stream.Stream;
028
029import org.apache.commons.io.FilenameUtils;
030
031/**
032 * Filters files using the supplied wildcards.
033 * <p>
034 * This filter selects files, but not directories, based on one or more wildcards
035 * and using case-sensitive comparison.
036 * </p>
037 * <p>
038 * The wildcard matcher uses the characters '?' and '*' to represent a
039 * single or multiple wildcard characters.
040 * This is the same as often found on DOS/Unix command lines.
041 * The extension check is case-sensitive.
042 * See {@link FilenameUtils#wildcardMatch(String, String)} for more information.
043 * </p>
044 * <p>
045 * For example:
046 * </p>
047 * <h2>Using Classic IO</h2>
048 * <pre>
049 * File dir = FileUtils.current();
050 * FileFilter fileFilter = new WildcardFilter("*test*.java~*~");
051 * File[] files = dir.listFiles(fileFilter);
052 * for (String file : files) {
053 *     System.out.println(file);
054 * }
055 * </pre>
056 *
057 * <h2>Using NIO</h2>
058 * <pre>
059 * final Path dir = PathUtils.current();
060 * final AccumulatorPathVisitor visitor = AccumulatorPathVisitor.withLongCounters(new WildcardFilter("*test*.java~*~"));
061 * //
062 * // Walk one dir
063 * Files.<b>walkFileTree</b>(dir, Collections.emptySet(), 1, visitor);
064 * System.out.println(visitor.getPathCounters());
065 * System.out.println(visitor.getFileList());
066 * //
067 * visitor.getPathCounters().reset();
068 * //
069 * // Walk dir tree
070 * Files.<b>walkFileTree</b>(dir, visitor);
071 * System.out.println(visitor.getPathCounters());
072 * System.out.println(visitor.getDirList());
073 * System.out.println(visitor.getFileList());
074 * </pre>
075 * <h2>Deprecating Serialization</h2>
076 * <p>
077 * <em>Serialization is deprecated and will be removed in 3.0.</em>
078 * </p>
079 *
080 * @since 1.1
081 * @deprecated Use WildcardFileFilter. Deprecated as this class performs directory
082 * filtering which it shouldn't do, but that can't be removed due to compatibility.
083 */
084@Deprecated
085public class WildcardFilter extends AbstractFileFilter implements Serializable {
086
087    private static final long serialVersionUID = -5037645902506953517L;
088
089    /** The wildcards that will be used to match file names. */
090    private final String[] wildcards;
091
092    /**
093     * Constructs a new case-sensitive wildcard filter for a list of wildcards.
094     *
095     * @param wildcards  the list of wildcards to match
096     * @throws NullPointerException if the pattern list is null
097     * @throws ClassCastException if the list does not contain Strings
098     */
099    public WildcardFilter(final List<String> wildcards) {
100        Objects.requireNonNull(wildcards, "wildcards");
101        this.wildcards = wildcards.toArray(EMPTY_STRING_ARRAY);
102    }
103
104    /**
105     * Constructs a new case-sensitive wildcard filter for a single wildcard.
106     *
107     * @param wildcard  the wildcard to match
108     * @throws NullPointerException if the pattern is null
109     */
110    public WildcardFilter(final String wildcard) {
111        Objects.requireNonNull(wildcard, "wildcard");
112        this.wildcards = new String[] { wildcard };
113    }
114
115    /**
116     * Constructs a new case-sensitive wildcard filter for an array of wildcards.
117     *
118     * @param wildcards  the array of wildcards to match
119     * @throws NullPointerException if the pattern array is null
120     */
121    public WildcardFilter(final String... wildcards) {
122        Objects.requireNonNull(wildcards, "wildcards");
123        this.wildcards = wildcards.clone();
124    }
125
126    /**
127     * Checks to see if the file name matches one of the wildcards.
128     *
129     * @param file the file to check
130     * @return true if the file name matches one of the wildcards
131     */
132    @Override
133    public boolean accept(final File file) {
134        if (file.isDirectory()) {
135            return false;
136        }
137        return Stream.of(wildcards).anyMatch(wildcard -> FilenameUtils.wildcardMatch(file.getName(), wildcard));
138    }
139
140    /**
141     * Checks to see if the file name matches one of the wildcards.
142     *
143     * @param dir  the file directory
144     * @param name  the file name
145     * @return true if the file name matches one of the wildcards
146     */
147    @Override
148    public boolean accept(final File dir, final String name) {
149        if (dir != null && new File(dir, name).isDirectory()) {
150            return false;
151        }
152        return Stream.of(wildcards).anyMatch(wildcard -> FilenameUtils.wildcardMatch(name, wildcard));
153    }
154
155    /**
156     * Checks to see if the file name matches one of the wildcards.
157     * @param file the file to check
158     *
159     * @return true if the file name matches one of the wildcards
160     * @since 2.9.0
161     */
162    @Override
163    public FileVisitResult accept(final Path file, final BasicFileAttributes attributes) {
164        if (Files.isDirectory(file)) {
165            return FileVisitResult.TERMINATE;
166        }
167        return toDefaultFileVisitResult(
168                Stream.of(wildcards).anyMatch(wildcard -> FilenameUtils.wildcardMatch(Objects.toString(file.getFileName(), null), wildcard)));
169
170    }
171
172}