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