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     */
017    package org.apache.commons.io.filefilter;
018    
019    import java.io.File;
020    import java.io.Serializable;
021    import java.util.List;
022    
023    import org.apache.commons.io.FilenameUtils;
024    import 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 extension check is case-sensitive by .
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 < files.length; i++) {
044     *   System.out.println(files[i]);
045     * }
046     * </pre>
047     *
048     * @version $Id: WildcardFileFilter.java 1304058 2012-03-22 21:02:43Z sebb $
049     * @since 1.3
050     */
051    public class WildcardFileFilter extends AbstractFileFilter implements Serializable {
052    
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(String wildcard) {
065            this(wildcard, null);
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(String wildcard, 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         * The array is not cloned, so could be changed after constructing the
087         * instance. This would be inadvisable however.
088         *
089         * @param wildcards  the array of wildcards to match
090         * @throws IllegalArgumentException if the pattern array is null
091         */
092        public WildcardFileFilter(String[] wildcards) {
093            this(wildcards, null);
094        }
095    
096        /**
097         * Construct a new wildcard filter for an array of wildcards specifying case-sensitivity.
098         * <p>
099         * The array is not cloned, so could be changed after constructing the
100         * instance. This would be inadvisable however.
101         *
102         * @param wildcards  the array of wildcards to match, not null
103         * @param caseSensitivity  how to handle case sensitivity, null means case-sensitive
104         * @throws IllegalArgumentException if the pattern array is null
105         */
106        public WildcardFileFilter(String[] wildcards, IOCase caseSensitivity) {
107            if (wildcards == null) {
108                throw new IllegalArgumentException("The wildcard array must not be null");
109            }
110            this.wildcards = new String[wildcards.length];
111            System.arraycopy(wildcards, 0, this.wildcards, 0, wildcards.length);
112            this.caseSensitivity = caseSensitivity == null ? IOCase.SENSITIVE : caseSensitivity;
113        }
114    
115        /**
116         * Construct a new case-sensitive wildcard filter for a list of wildcards.
117         *
118         * @param wildcards  the list of wildcards to match, not null
119         * @throws IllegalArgumentException if the pattern list is null
120         * @throws ClassCastException if the list does not contain Strings
121         */
122        public WildcardFileFilter(List<String> wildcards) {
123            this(wildcards, null);
124        }
125    
126        /**
127         * Construct a new wildcard filter for a list of wildcards specifying case-sensitivity.
128         *
129         * @param wildcards  the list of wildcards to match, not null
130         * @param caseSensitivity  how to handle case sensitivity, null means case-sensitive
131         * @throws IllegalArgumentException if the pattern list is null
132         * @throws ClassCastException if the list does not contain Strings
133         */
134        public WildcardFileFilter(List<String> wildcards, IOCase caseSensitivity) {
135            if (wildcards == null) {
136                throw new IllegalArgumentException("The wildcard list must not be null");
137            }
138            this.wildcards = wildcards.toArray(new String[wildcards.size()]);
139            this.caseSensitivity = caseSensitivity == null ? IOCase.SENSITIVE : caseSensitivity;
140        }
141    
142        //-----------------------------------------------------------------------
143        /**
144         * Checks to see if the filename matches one of the wildcards.
145         *
146         * @param dir  the file directory (ignored)
147         * @param name  the filename
148         * @return true if the filename matches one of the wildcards
149         */
150        @Override
151        public boolean accept(File dir, String name) {
152            for (String wildcard : wildcards) {
153                if (FilenameUtils.wildcardMatch(name, wildcard, caseSensitivity)) {
154                    return true;
155                }
156            }
157            return false;
158        }
159    
160        /**
161         * Checks to see if the filename matches one of the wildcards.
162         *
163         * @param file  the file to check
164         * @return true if the filename matches one of the wildcards
165         */
166        @Override
167        public boolean accept(File file) {
168            String name = file.getName();
169            for (String wildcard : wildcards) {
170                if (FilenameUtils.wildcardMatch(name, wildcard, caseSensitivity)) {
171                    return true;
172                }
173            }
174            return false;
175        }
176    
177        /**
178         * Provide a String representaion of this file filter.
179         *
180         * @return a String representaion
181         */
182        @Override
183        public String toString() {
184            StringBuilder buffer = new StringBuilder();
185            buffer.append(super.toString());
186            buffer.append("(");
187            if (wildcards != null) {
188                for (int i = 0; i < wildcards.length; i++) {
189                    if (i > 0) {
190                        buffer.append(",");
191                    }
192                    buffer.append(wildcards[i]);
193                }
194            }
195            buffer.append(")");
196            return buffer.toString();
197        }
198    
199    }