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     * @author Jason Anderson
049     * @version $Revision: 1004077 $ $Date: 2010-10-03 20:58:42 -0400 (Sun, 03 Oct 2010) $
050     * @since Commons IO 1.3
051     */
052    public class WildcardFileFilter extends AbstractFileFilter implements Serializable {
053    
054        /** The wildcards that will be used to match filenames. */
055        private final String[] wildcards;
056        /** Whether the comparison is case sensitive. */
057        private final IOCase caseSensitivity;
058    
059        /**
060         * Construct a new case-sensitive wildcard filter for a single wildcard.
061         *
062         * @param wildcard  the wildcard to match
063         * @throws IllegalArgumentException if the pattern is null
064         */
065        public WildcardFileFilter(String wildcard) {
066            this(wildcard, null);
067        }
068    
069        /**
070         * Construct a new wildcard filter for a single wildcard specifying case-sensitivity.
071         *
072         * @param wildcard  the wildcard to match, not null
073         * @param caseSensitivity  how to handle case sensitivity, null means case-sensitive
074         * @throws IllegalArgumentException if the pattern is null
075         */
076        public WildcardFileFilter(String wildcard, IOCase caseSensitivity) {
077            if (wildcard == null) {
078                throw new IllegalArgumentException("The wildcard must not be null");
079            }
080            this.wildcards = new String[] { wildcard };
081            this.caseSensitivity = (caseSensitivity == null ? IOCase.SENSITIVE : caseSensitivity);
082        }
083    
084        /**
085         * Construct a new case-sensitive wildcard filter for an array of wildcards.
086         * <p>
087         * The array is not cloned, so could be changed after constructing the
088         * instance. This would be inadvisable however.
089         *
090         * @param wildcards  the array of wildcards to match
091         * @throws IllegalArgumentException if the pattern array is null
092         */
093        public WildcardFileFilter(String[] wildcards) {
094            this(wildcards, null);
095        }
096    
097        /**
098         * Construct a new wildcard filter for an array of wildcards specifying case-sensitivity.
099         * <p>
100         * The array is not cloned, so could be changed after constructing the
101         * instance. This would be inadvisable however.
102         *
103         * @param wildcards  the array of wildcards to match, not null
104         * @param caseSensitivity  how to handle case sensitivity, null means case-sensitive
105         * @throws IllegalArgumentException if the pattern array is null
106         */
107        public WildcardFileFilter(String[] wildcards, IOCase caseSensitivity) {
108            if (wildcards == null) {
109                throw new IllegalArgumentException("The wildcard array must not be null");
110            }
111            this.wildcards = new String[wildcards.length];
112            System.arraycopy(wildcards, 0, this.wildcards, 0, wildcards.length);
113            this.caseSensitivity = (caseSensitivity == null ? IOCase.SENSITIVE : caseSensitivity);
114        }
115    
116        /**
117         * Construct a new case-sensitive wildcard filter for a list of wildcards.
118         *
119         * @param wildcards  the list of wildcards to match, not null
120         * @throws IllegalArgumentException if the pattern list is null
121         * @throws ClassCastException if the list does not contain Strings
122         */
123        public WildcardFileFilter(List<String> wildcards) {
124            this(wildcards, null);
125        }
126    
127        /**
128         * Construct a new wildcard filter for a list of wildcards specifying case-sensitivity.
129         *
130         * @param wildcards  the list of wildcards to match, not null
131         * @param caseSensitivity  how to handle case sensitivity, null means case-sensitive
132         * @throws IllegalArgumentException if the pattern list is null
133         * @throws ClassCastException if the list does not contain Strings
134         */
135        public WildcardFileFilter(List<String> wildcards, IOCase caseSensitivity) {
136            if (wildcards == null) {
137                throw new IllegalArgumentException("The wildcard list must not be null");
138            }
139            this.wildcards = wildcards.toArray(new String[wildcards.size()]);
140            this.caseSensitivity = (caseSensitivity == null ? IOCase.SENSITIVE : caseSensitivity);
141        }
142    
143        //-----------------------------------------------------------------------
144        /**
145         * Checks to see if the filename matches one of the wildcards.
146         *
147         * @param dir  the file directory
148         * @param name  the filename
149         * @return true if the filename matches one of the wildcards
150         */
151        @Override
152        public boolean accept(File dir, String name) {
153            for (String wildcard : wildcards) {
154                if (FilenameUtils.wildcardMatch(name, wildcard, caseSensitivity)) {
155                    return true;
156                }
157            }
158            return false;
159        }
160    
161        /**
162         * Checks to see if the filename matches one of the wildcards.
163         *
164         * @param file  the file to check
165         * @return true if the filename matches one of the wildcards
166         */
167        @Override
168        public boolean accept(File file) {
169            String name = file.getName();
170            for (String wildcard : wildcards) {
171                if (FilenameUtils.wildcardMatch(name, wildcard, caseSensitivity)) {
172                    return true;
173                }
174            }
175            return false;
176        }
177    
178        /**
179         * Provide a String representaion of this file filter.
180         *
181         * @return a String representaion
182         */
183        @Override
184        public String toString() {
185            StringBuilder buffer = new StringBuilder();
186            buffer.append(super.toString());
187            buffer.append("(");
188            if (wildcards != null) {
189                for (int i = 0; i < wildcards.length; i++) {
190                    if (i > 0) {
191                        buffer.append(",");
192                    }
193                    buffer.append(wildcards[i]);
194                }
195            }
196            buffer.append(")");
197            return buffer.toString();
198        }
199    
200    }