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.util.List;
022
023import org.apache.commons.io.FilenameUtils;
024import org.apache.commons.io.IOCase;
025
026/**
027 * Filters files using the supplied wildcards.
028 * <p>
029 * This filter selects files and directories based on one or more wildcards.
030 * Testing is case-sensitive by default, but this can be configured.
031 * <p>
032 * The wildcard matcher uses the characters '?' and '*' to represent a
033 * single or multiple wildcard characters.
034 * This is the same as often found on Dos/Unix command lines.
035 * The check is case-sensitive by default.
036 * See {@link FilenameUtils#wildcardMatchOnSystem} for more information.
037 * <p>
038 * For example:
039 * <pre>
040 * File dir = new File(".");
041 * FileFilter fileFilter = new WildcardFileFilter("*test*.java~*~");
042 * File[] files = dir.listFiles(fileFilter);
043 * for (int i = 0; i &lt; files.length; i++) {
044 *   System.out.println(files[i]);
045 * }
046 * </pre>
047 *
048 * @since 1.3
049 */
050public class WildcardFileFilter extends AbstractFileFilter implements Serializable {
051
052    private static final long serialVersionUID = -7426486598995782105L;
053    /** The wildcards that will be used to match filenames. */
054    private final String[] wildcards;
055    /** Whether the comparison is case sensitive. */
056    private final IOCase caseSensitivity;
057
058    /**
059     * Construct a new case-sensitive wildcard filter for a single wildcard.
060     *
061     * @param wildcard  the wildcard to match
062     * @throws IllegalArgumentException if the pattern is null
063     */
064    public WildcardFileFilter(final String wildcard) {
065        this(wildcard, IOCase.SENSITIVE);
066    }
067
068    /**
069     * Construct a new wildcard filter for a single wildcard specifying case-sensitivity.
070     *
071     * @param wildcard  the wildcard to match, not null
072     * @param caseSensitivity  how to handle case sensitivity, null means case-sensitive
073     * @throws IllegalArgumentException if the pattern is null
074     */
075    public WildcardFileFilter(final String wildcard, final IOCase caseSensitivity) {
076        if (wildcard == null) {
077            throw new IllegalArgumentException("The wildcard must not be null");
078        }
079        this.wildcards = new String[] { wildcard };
080        this.caseSensitivity = caseSensitivity == null ? IOCase.SENSITIVE : caseSensitivity;
081    }
082
083    /**
084     * Construct a new case-sensitive wildcard filter for an array of wildcards.
085     * <p>
086     *
087     * @param wildcards  the array of wildcards to match
088     * @throws IllegalArgumentException if the pattern array is null
089     */
090    public WildcardFileFilter(final String[] wildcards) {
091        this(wildcards, IOCase.SENSITIVE);
092    }
093
094    /**
095     * Construct a new wildcard filter for an array of wildcards specifying case-sensitivity.
096     * <p>
097     *
098     * @param wildcards  the array of wildcards to match, not null
099     * @param caseSensitivity  how to handle case sensitivity, null means case-sensitive
100     * @throws IllegalArgumentException if the pattern array is null
101     */
102    public WildcardFileFilter(final String[] wildcards, final IOCase caseSensitivity) {
103        if (wildcards == null) {
104            throw new IllegalArgumentException("The wildcard array must not be null");
105        }
106        this.wildcards = new String[wildcards.length];
107        System.arraycopy(wildcards, 0, this.wildcards, 0, wildcards.length);
108        this.caseSensitivity = caseSensitivity == null ? IOCase.SENSITIVE : caseSensitivity;
109    }
110
111    /**
112     * Construct a new case-sensitive wildcard filter for a list of wildcards.
113     *
114     * @param wildcards  the list of wildcards to match, not null
115     * @throws IllegalArgumentException if the pattern list is null
116     * @throws ClassCastException if the list does not contain Strings
117     */
118    public WildcardFileFilter(final List<String> wildcards) {
119        this(wildcards, IOCase.SENSITIVE);
120    }
121
122    /**
123     * Construct a new wildcard filter for a list of wildcards specifying case-sensitivity.
124     *
125     * @param wildcards  the list of wildcards to match, not null
126     * @param caseSensitivity  how to handle case sensitivity, null means case-sensitive
127     * @throws IllegalArgumentException if the pattern list is null
128     * @throws ClassCastException if the list does not contain Strings
129     */
130    public WildcardFileFilter(final List<String> wildcards, final IOCase caseSensitivity) {
131        if (wildcards == null) {
132            throw new IllegalArgumentException("The wildcard list must not be null");
133        }
134        this.wildcards = wildcards.toArray(new String[wildcards.size()]);
135        this.caseSensitivity = caseSensitivity == null ? IOCase.SENSITIVE : caseSensitivity;
136    }
137
138    //-----------------------------------------------------------------------
139    /**
140     * Checks to see if the filename matches one of the wildcards.
141     *
142     * @param dir  the file directory (ignored)
143     * @param name  the filename
144     * @return true if the filename matches one of the wildcards
145     */
146    @Override
147    public boolean accept(final File dir, final String name) {
148        for (final String wildcard : wildcards) {
149            if (FilenameUtils.wildcardMatch(name, wildcard, caseSensitivity)) {
150                return true;
151            }
152        }
153        return false;
154    }
155
156    /**
157     * Checks to see if the filename matches one of the wildcards.
158     *
159     * @param file  the file to check
160     * @return true if the filename matches one of the wildcards
161     */
162    @Override
163    public boolean accept(final File file) {
164        final String name = file.getName();
165        for (final String wildcard : wildcards) {
166            if (FilenameUtils.wildcardMatch(name, wildcard, caseSensitivity)) {
167                return true;
168            }
169        }
170        return false;
171    }
172
173    /**
174     * Provide a String representation of this file filter.
175     *
176     * @return a String representation
177     */
178    @Override
179    public String toString() {
180        final StringBuilder buffer = new StringBuilder();
181        buffer.append(super.toString());
182        buffer.append("(");
183        if (wildcards != null) {
184            for (int i = 0; i < wildcards.length; i++) {
185                if (i > 0) {
186                    buffer.append(",");
187                }
188                buffer.append(wildcards[i]);
189            }
190        }
191        buffer.append(")");
192        return buffer.toString();
193    }
194
195}