    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}