    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.FileFilter;
    021    import java.io.FilenameFilter;
    022    import java.util.ArrayList;
    023    import java.util.Arrays;
    024    import java.util.Collection;
    025    import java.util.Date;
    026    import java.util.HashSet;
    027    import java.util.List;
    028    import java.util.Set;
    029
    030    import org.apache.commons.io.IOCase;
    031
    032    /**
    033     * Useful utilities for working with file filters. It provides access to all
    034     * file filter implementations in this package so you don't have to import
    035     * every class you use.
    036     *
    037     * @since Commons IO 1.0
    038     * @version $Id: FileFilterUtils.java 1005099 2010-10-06 16:13:01Z niallp $
    039     *
    040     * @author Stephen Colebourne
    041     * @author Jeremias Maerki
    042     * @author Masato Tezuka
    043     * @author Rahul Akolkar
    044     */
    045    public class FileFilterUtils {
    046
    047        /**
    048         * FileFilterUtils is not normally instantiated.
    049         */
    050        public FileFilterUtils() {
    051        }
    052
    053        //-----------------------------------------------------------------------
    054
    055        /**
    056         * <p>
    057         * Applies an {@link IOFileFilter} to the provided {@link File}
    058         * objects. The resulting array is a subset of the original file list that
    059         * matches the provided filter.
    060         * </p>
    061         *
    062         * <p>
    063         * The {@link Set} returned by this method is not guaranteed to be thread safe.
    064         * </p>
    065         *
    066         * <pre>
    067         * Set&lt;File&gt; allFiles = ...
    068         * Set&lt;File&gt; javaFiles = FileFilterUtils.filterSet(allFiles,
    069         *     FileFilterUtils.suffixFileFilter(".java"));
    070         * </pre>
    071         * @param filter the filter to apply to the set of files.
    072         * @param files the array of files to apply the filter to.
    073         *
    074         * @return a subset of <code>files</code> that is accepted by the
    075         *         file filter.
    076         * @throws IllegalArgumentException if the filter is <code>null</code>
    077         *         or <code>files</code> contains a <code>null</code> value.
    078         *
    079         * @since Commons IO 2.0
    080         */
    081        public static File[] filter(IOFileFilter filter, File... files) {
    082            if (filter == null) {
    083                throw new IllegalArgumentException("file filter is null");
    084            }
    085            if (files == null) {
    086                return new File[0];
    087            }
    088            List<File> acceptedFiles = new ArrayList<File>();
    089            for (File file : files) {
    090                if (file == null) {
    091                    throw new IllegalArgumentException("file array contains null");
    092                }
    093                if (filter.accept(file)) {
    094                    acceptedFiles.add(file);
    095                }
    096            }
    097            return acceptedFiles.toArray(new File[acceptedFiles.size()]);
    098        }
    099
    100        /**
    101         * <p>
    102         * Applies an {@link IOFileFilter} to the provided {@link File}
    103         * objects. The resulting array is a subset of the original file list that
    104         * matches the provided filter.
    105         * </p>
    106         *
    107         * <p>
    108         * The {@link Set} returned by this method is not guaranteed to be thread safe.
    109         * </p>
    110         *
    111         * <pre>
    112         * Set&lt;File&gt; allFiles = ...
    113         * Set&lt;File&gt; javaFiles = FileFilterUtils.filterSet(allFiles,
    114         *     FileFilterUtils.suffixFileFilter(".java"));
    115         * </pre>
    116         * @param filter the filter to apply to the set of files.
    117         * @param files the array of files to apply the filter to.
    118         *
    119         * @return a subset of <code>files</code> that is accepted by the
    120         *         file filter.
    121         * @throws IllegalArgumentException if the filter is <code>null</code>
    122         *         or <code>files</code> contains a <code>null</code> value.
    123         *
    124         * @since Commons IO 2.0
    125         */
    126        public static File[] filter(IOFileFilter filter, Iterable<File> files) {
    127            List<File> acceptedFiles = filterList(filter, files);
    128            return acceptedFiles.toArray(new File[acceptedFiles.size()]);
    129        }
    130
    131        /**
    132         * <p>
    133         * Applies an {@link IOFileFilter} to the provided {@link File}
    134         * objects. The resulting list is a subset of the original files that
    135         * matches the provided filter.
    136         * </p>
    137         *
    138         * <p>
    139         * The {@link List} returned by this method is not guaranteed to be thread safe.
    140         * </p>
    141         *
    142         * <pre>
    143         * List&lt;File&gt; filesAndDirectories = ...
    144         * List&lt;File&gt; directories = FileFilterUtils.filterList(filesAndDirectories,
    145         *     FileFilterUtils.directoryFileFilter());
    146         * </pre>
    147         * @param filter the filter to apply to each files in the list.
    148         * @param files the collection of files to apply the filter to.
    149         *
    150         * @return a subset of <code>files</code> that is accepted by the
    151         *         file filter.
    152         * @throws IllegalArgumentException if the filter is <code>null</code>
    153         *         or <code>files</code> contains a <code>null</code> value.
    154         * @since Commons IO 2.0
    155         */
    156        public static List<File> filterList(IOFileFilter filter, Iterable<File> files) {
    157            return filter(filter, files, new ArrayList<File>());
    158        }
    159
    160        /**
    161         * <p>
    162         * Applies an {@link IOFileFilter} to the provided {@link File}
    163         * objects. The resulting list is a subset of the original files that
    164         * matches the provided filter.
    165         * </p>
    166         *
    167         * <p>
    168         * The {@link List} returned by this method is not guaranteed to be thread safe.
    169         * </p>
    170         *
    171         * <pre>
    172         * List&lt;File&gt; filesAndDirectories = ...
    173         * List&lt;File&gt; directories = FileFilterUtils.filterList(filesAndDirectories,
    174         *     FileFilterUtils.directoryFileFilter());
    175         * </pre>
    176         * @param filter the filter to apply to each files in the list.
    177         * @param files the collection of files to apply the filter to.
    178         *
    179         * @return a subset of <code>files</code> that is accepted by the
    180         *         file filter.
    181         * @throws IllegalArgumentException if the filter is <code>null</code>
    182         *         or <code>files</code> contains a <code>null</code> value.
    183         * @since Commons IO 2.0
    184         */
    185        public static List<File> filterList(IOFileFilter filter, File... files) {
    186            File[] acceptedFiles = filter(filter, files);
    187            return Arrays.asList(acceptedFiles);
    188        }
    189
    190        /**
    191         * <p>
    192         * Applies an {@link IOFileFilter} to the provided {@link File}
    193         * objects. The resulting set is a subset of the original file list that
    194         * matches the provided filter.
    195         * </p>
    196         *
    197         * <p>
    198         * The {@link Set} returned by this method is not guaranteed to be thread safe.
    199         * </p>
    200         *
    201         * <pre>
    202         * Set&lt;File&gt; allFiles = ...
    203         * Set&lt;File&gt; javaFiles = FileFilterUtils.filterSet(allFiles,
    204         *     FileFilterUtils.suffixFileFilter(".java"));
    205         * </pre>
    206         * @param filter the filter to apply to the set of files.
    207         * @param files the collection of files to apply the filter to.
    208         *
    209         * @return a subset of <code>files</code> that is accepted by the
    210         *         file filter.
    211         * @throws IllegalArgumentException if the filter is <code>null</code>
    212         *         or <code>files</code> contains a <code>null</code> value.
    213         *
    214         * @since Commons IO 2.0
    215         */
    216        public static Set<File> filterSet(IOFileFilter filter, File... files) {
    217            File[] acceptedFiles = filter(filter, files);
    218            return new HashSet<File>(Arrays.asList(acceptedFiles));
    219        }
    220
    221        /**
    222         * <p>
    223         * Applies an {@link IOFileFilter} to the provided {@link File}
    224         * objects. The resulting set is a subset of the original file list that
    225         * matches the provided filter.
    226         * </p>
    227         *
    228         * <p>
    229         * The {@link Set} returned by this method is not guaranteed to be thread safe.
    230         * </p>
    231         *
    232         * <pre>
    233         * Set&lt;File&gt; allFiles = ...
    234         * Set&lt;File&gt; javaFiles = FileFilterUtils.filterSet(allFiles,
    235         *     FileFilterUtils.suffixFileFilter(".java"));
    236         * </pre>
    237         * @param filter the filter to apply to the set of files.
    238         * @param files the collection of files to apply the filter to.
    239         *
    240         * @return a subset of <code>files</code> that is accepted by the
    241         *         file filter.
    242         * @throws IllegalArgumentException if the filter is <code>null</code>
    243         *         or <code>files</code> contains a <code>null</code> value.
    244         *
    245         * @since Commons IO 2.0
    246         */
    247        public static Set<File> filterSet(IOFileFilter filter, Iterable<File> files) {
    248            return filter(filter, files, new HashSet<File>());
    249        }
    250
    251        /**
    252         * <p>
    253         * Applies an {@link IOFileFilter} to the provided {@link File}
    254         * objects and appends the accepted files to the other supplied collection.
    255         * </p>
    256         *
    257         * <pre>
    258         * List&lt;File&gt; files = ...
    259         * List&lt;File&gt; directories = FileFilterUtils.filterList(files,
    260         *     FileFilterUtils.sizeFileFilter(FileUtils.FIFTY_MB),
    261         *         new ArrayList&lt;File&gt;());
    262         * </pre>
    263         * @param filter the filter to apply to the collection of files.
    264         * @param files the collection of files to apply the filter to.
    265         * @param acceptedFiles the list of files to add accepted files to.
    266         *
    267         * @param <T> the type of the file collection.
    268         * @return a subset of <code>files</code> that is accepted by the
    269         *         file filter.
    270         * @throws IllegalArgumentException if the filter is <code>null</code>
    271         *         or <code>files</code> contains a <code>null</code> value.
    272         */
    273        private static <T extends Collection<File>> T filter(IOFileFilter filter,
    274                Iterable<File> files, T acceptedFiles) {
    275            if (filter == null) {
    276                throw new IllegalArgumentException("file filter is null");
    277            }
    278            if (files != null) {
    279                for (File file : files) {
    280                    if (file == null) {
    281                        throw new IllegalArgumentException("file collection contains null");
    282                    }
    283                    if (filter.accept(file)) {
    284                        acceptedFiles.add(file);
    285                    }
    286                }
    287            }
    288            return acceptedFiles;
    289        }
    290
    291        /**
    292         * Returns a filter that returns true if the filename starts with the specified text.
    293         *
    294         * @param prefix  the filename prefix
    295         * @return a prefix checking filter
    296         * @see PrefixFileFilter
    297         */
    298        public static IOFileFilter prefixFileFilter(String prefix) {
    299            return new PrefixFileFilter(prefix);
    300        }
    301
    302        /**
    303         * Returns a filter that returns true if the filename starts with the specified text.
    304         *
    305         * @param prefix  the filename prefix
    306         * @param caseSensitivity  how to handle case sensitivity, null means case-sensitive
    307         * @return a prefix checking filter
    308         * @see PrefixFileFilter
    309         * @since Commons IO 2.0
    310         */
    311        public static IOFileFilter prefixFileFilter(String prefix, IOCase caseSensitivity) {
    312            return new PrefixFileFilter(prefix, caseSensitivity);
    313        }
    314
    315        /**
    316         * Returns a filter that returns true if the filename ends with the specified text.
    317         *
    318         * @param suffix  the filename suffix
    319         * @return a suffix checking filter
    320         * @see SuffixFileFilter
    321         */
    322        public static IOFileFilter suffixFileFilter(String suffix) {
    323            return new SuffixFileFilter(suffix);
    324        }
    325
    326        /**
    327         * Returns a filter that returns true if the filename ends with the specified text.
    328         *
    329         * @param suffix  the filename suffix
    330         * @param caseSensitivity  how to handle case sensitivity, null means case-sensitive
    331         * @return a suffix checking filter
    332         * @see SuffixFileFilter
    333         * @since Commons IO 2.0
    334         */
    335        public static IOFileFilter suffixFileFilter(String suffix, IOCase caseSensitivity) {
    336            return new SuffixFileFilter(suffix, caseSensitivity);
    337        }
    338
    339        /**
    340         * Returns a filter that returns true if the filename matches the specified text.
    341         *
    342         * @param name  the filename
    343         * @return a name checking filter
    344         * @see NameFileFilter
    345         */
    346        public static IOFileFilter nameFileFilter(String name) {
    347            return new NameFileFilter(name);
    348        }
    349
    350        /**
    351         * Returns a filter that returns true if the filename matches the specified text.
    352         *
    353         * @param name  the filename
    354         * @param caseSensitivity  how to handle case sensitivity, null means case-sensitive
    355         * @return a name checking filter
    356         * @see NameFileFilter
    357         * @since Commons IO 2.0
    358         */
    359        public static IOFileFilter nameFileFilter(String name, IOCase caseSensitivity) {
    360            return new NameFileFilter(name, caseSensitivity);
    361        }
    362
    363        /**
    364         * Returns a filter that checks if the file is a directory.
    365         *
    366         * @return file filter that accepts only directories and not files
    367         * @see DirectoryFileFilter#DIRECTORY
    368         */
    369        public static IOFileFilter directoryFileFilter() {
    370            return DirectoryFileFilter.DIRECTORY;
    371        }
    372
    373        /**
    374         * Returns a filter that checks if the file is a file (and not a directory).
    375         *
    376         * @return file filter that accepts only files and not directories
    377         * @see FileFileFilter#FILE
    378         */
    379        public static IOFileFilter fileFileFilter() {
    380            return FileFileFilter.FILE;
    381        }
    382
    383        //-----------------------------------------------------------------------
    384        /**
    385         * Returns a filter that ANDs the two specified filters.
    386         *
    387         * @param filter1  the first filter
    388         * @param filter2  the second filter
    389         * @return a filter that ANDs the two specified filters
    390         * @see #and(IOFileFilter...)
    391         * @see AndFileFilter
    392         * @deprecated use {@link #and(IOFileFilter...)}
    393         */
    394        @Deprecated
    395        public static IOFileFilter andFileFilter(IOFileFilter filter1, IOFileFilter filter2) {
    396            return new AndFileFilter(filter1, filter2);
    397        }
    398
    399        /**
    400         * Returns a filter that ORs the two specified filters.
    401         *
    402         * @param filter1  the first filter
    403         * @param filter2  the second filter
    404         * @return a filter that ORs the two specified filters
    405         * @see #or(IOFileFilter...)
    406         * @see OrFileFilter
    407         * @deprecated use {@link #or(IOFileFilter...)}
    408         */
    409        @Deprecated
    410        public static IOFileFilter orFileFilter(IOFileFilter filter1, IOFileFilter filter2) {
    411            return new OrFileFilter(filter1, filter2);
    412        }
    413
    414        /**
    415         * Returns a filter that ANDs the specified filters.
    416         *
    417         * @param filters the IOFileFilters that will be ANDed together.
    418         * @return a filter that ANDs the specified filters
    419         *
    420         * @throws IllegalArgumentException if the filters are null or contain a
    421         *         null value.
    422         * @see AndFileFilter
    423         * @since Commons IO 2.0
    424         */
    425        public static IOFileFilter and(IOFileFilter... filters) {
    426            return new AndFileFilter(toList(filters));
    427        }
    428
    429        /**
    430         * Returns a filter that ORs the specified filters.
    431         *
    432         * @param filters the IOFileFilters that will be ORed together.
    433         * @return a filter that ORs the specified filters
    434         *
    435         * @throws IllegalArgumentException if the filters are null or contain a
    436         *         null value.
    437         * @see OrFileFilter
    438         * @since Commons IO 2.0
    439         */
    440        public static IOFileFilter or(IOFileFilter... filters) {
    441            return new OrFileFilter(toList(filters));
    442        }
    443
    444        /**
    445         * Create a List of file filters.
    446         *
    447         * @param filters The file filters
    448         * @return The list of file filters
    449         * @throws IllegalArgumentException if the filters are null or contain a
    450         *         null value.
    451         * @since Commons IO 2.0
    452         */
    453        public static List<IOFileFilter> toList(IOFileFilter... filters) {
    454            if (filters == null) {
    455                throw new IllegalArgumentException("The filters must not be null");
    456            }
    457            List<IOFileFilter> list = new ArrayList<IOFileFilter>(filters.length);
    458            for (int i = 0; i < filters.length; i++) {
    459                if (filters[i] == null) {
    460                    throw new IllegalArgumentException("The filter[" + i + "] is null");
    461                }
    462                list.add(filters[i]);
    463            }
    464            return list;
    465        }
    466
    467        /**
    468         * Returns a filter that NOTs the specified filter.
    469         *
    470         * @param filter  the filter to invert
    471         * @return a filter that NOTs the specified filter
    472         * @see NotFileFilter
    473         */
    474        public static IOFileFilter notFileFilter(IOFileFilter filter) {
    475            return new NotFileFilter(filter);
    476        }
    477
    478        //-----------------------------------------------------------------------
    479        /**
    480         * Returns a filter that always returns true.
    481         *
    482         * @return a true filter
    483         * @see TrueFileFilter#TRUE
    484         */
    485        public static IOFileFilter trueFileFilter() {
    486            return TrueFileFilter.TRUE;
    487        }
    488
    489        /**
    490         * Returns a filter that always returns false.
    491         *
    492         * @return a false filter
    493         * @see FalseFileFilter#FALSE
    494         */
    495        public static IOFileFilter falseFileFilter() {
    496            return FalseFileFilter.FALSE;
    497        }
    498
    499        //-----------------------------------------------------------------------
    500        /**
    501         * Returns an <code>IOFileFilter</code> that wraps the
    502         * <code>FileFilter</code> instance.
    503         *
    504         * @param filter  the filter to be wrapped
    505         * @return a new filter that implements IOFileFilter
    506         * @see DelegateFileFilter
    507         */
    508        public static IOFileFilter asFileFilter(FileFilter filter) {
    509            return new DelegateFileFilter(filter);
    510        }
    511
    512        /**
    513         * Returns an <code>IOFileFilter</code> that wraps the
    514         * <code>FilenameFilter</code> instance.
    515         *
    516         * @param filter  the filter to be wrapped
    517         * @return a new filter that implements IOFileFilter
    518         * @see DelegateFileFilter
    519         */
    520        public static IOFileFilter asFileFilter(FilenameFilter filter) {
    521            return new DelegateFileFilter(filter);
    522        }
    523
    524        //-----------------------------------------------------------------------
    525        /**
    526         * Returns a filter that returns true if the file was last modified after
    527         * the specified cutoff time.
    528         *
    529         * @param cutoff  the time threshold
    530         * @return an appropriately configured age file filter
    531         * @see AgeFileFilter
    532         * @since Commons IO 1.2
    533         */
    534        public static IOFileFilter ageFileFilter(long cutoff) {
    535            return new AgeFileFilter(cutoff);
    536        }
    537
    538        /**
    539         * Returns a filter that filters files based on a cutoff time.
    540         *
    541         * @param cutoff  the time threshold
    542         * @param acceptOlder  if true, older files get accepted, if false, newer
    543         * @return an appropriately configured age file filter
    544         * @see AgeFileFilter
    545         * @since Commons IO 1.2
    546         */
    547        public static IOFileFilter ageFileFilter(long cutoff, boolean acceptOlder) {
    548            return new AgeFileFilter(cutoff, acceptOlder);
    549        }
    550
    551        /**
    552         * Returns a filter that returns true if the file was last modified after
    553         * the specified cutoff date.
    554         *
    555         * @param cutoffDate  the time threshold
    556         * @return an appropriately configured age file filter
    557         * @see AgeFileFilter
    558         * @since Commons IO 1.2
    559         */
    560        public static IOFileFilter ageFileFilter(Date cutoffDate) {
    561            return new AgeFileFilter(cutoffDate);
    562        }
    563
    564        /**
    565         * Returns a filter that filters files based on a cutoff date.
    566         *
    567         * @param cutoffDate  the time threshold
    568         * @param acceptOlder  if true, older files get accepted, if false, newer
    569         * @return an appropriately configured age file filter
    570         * @see AgeFileFilter
    571         * @since Commons IO 1.2
    572         */
    573        public static IOFileFilter ageFileFilter(Date cutoffDate, boolean acceptOlder) {
    574            return new AgeFileFilter(cutoffDate, acceptOlder);
    575        }
    576
    577        /**
    578         * Returns a filter that returns true if the file was last modified after
    579         * the specified reference file.
    580         *
    581         * @param cutoffReference  the file whose last modification
    582         *        time is usesd as the threshold age of the files
    583         * @return an appropriately configured age file filter
    584         * @see AgeFileFilter
    585         * @since Commons IO 1.2
    586         */
    587        public static IOFileFilter ageFileFilter(File cutoffReference) {
    588            return new AgeFileFilter(cutoffReference);
    589        }
    590
    591        /**
    592         * Returns a filter that filters files based on a cutoff reference file.
    593         *
    594         * @param cutoffReference  the file whose last modification
    595         *        time is usesd as the threshold age of the files
    596         * @param acceptOlder  if true, older files get accepted, if false, newer
    597         * @return an appropriately configured age file filter
    598         * @see AgeFileFilter
    599         * @since Commons IO 1.2
    600         */
    601        public static IOFileFilter ageFileFilter(File cutoffReference, boolean acceptOlder) {
    602            return new AgeFileFilter(cutoffReference, acceptOlder);
    603        }
    604
    605        //-----------------------------------------------------------------------
    606        /**
    607         * Returns a filter that returns true if the file is bigger than a certain size.
    608         *
    609         * @param threshold  the file size threshold
    610         * @return an appropriately configured SizeFileFilter
    611         * @see SizeFileFilter
    612         * @since Commons IO 1.2
    613         */
    614        public static IOFileFilter sizeFileFilter(long threshold) {
    615            return new SizeFileFilter(threshold);
    616        }
    617
    618        /**
    619         * Returns a filter that filters based on file size.
    620         *
    621         * @param threshold  the file size threshold
    622         * @param acceptLarger  if true, larger files get accepted, if false, smaller
    623         * @return an appropriately configured SizeFileFilter
    624         * @see SizeFileFilter
    625         * @since Commons IO 1.2
    626         */
    627        public static IOFileFilter sizeFileFilter(long threshold, boolean acceptLarger) {
    628            return new SizeFileFilter(threshold, acceptLarger);
    629        }
    630
    631        /**
    632         * Returns a filter that accepts files whose size is &gt;= minimum size
    633         * and &lt;= maximum size.
    634         *
    635         * @param minSizeInclusive the minimum file size (inclusive)
    636         * @param maxSizeInclusive the maximum file size (inclusive)
    637         * @return an appropriately configured IOFileFilter
    638         * @see SizeFileFilter
    639         * @since Commons IO 1.3
    640         */
    641        public static IOFileFilter sizeRangeFileFilter(long minSizeInclusive, long maxSizeInclusive ) {
    642            IOFileFilter minimumFilter = new SizeFileFilter(minSizeInclusive, true);
    643            IOFileFilter maximumFilter = new SizeFileFilter(maxSizeInclusive + 1L, false);
    644            return new AndFileFilter(minimumFilter, maximumFilter);
    645        }
    646
    647        /**
    648         * Returns a filter that accepts files that begin with the provided magic
    649         * number.
    650         *
    651         * @param magicNumber the magic number (byte sequence) to match at the
    652         *        beginning of each file.
    653         *
    654         * @return an IOFileFilter that accepts files beginning with the provided
    655         *         magic number.
    656         *
    657         * @throws IllegalArgumentException if <code>magicNumber</code> is
    658         *         <code>null</code> or the empty String.
    659         * @see MagicNumberFileFilter
    660         * @since Commons IO 2.0
    661         */
    662        public static IOFileFilter magicNumberFileFilter(String magicNumber) {
    663            return new MagicNumberFileFilter(magicNumber);
    664        }
    665
    666        /**
    667         * Returns a filter that accepts files that contains the provided magic
    668         * number at a specified offset within the file.
    669         *
    670         * @param magicNumber the magic number (byte sequence) to match at the
    671         *        provided offset in each file.
    672         * @param offset the offset within the files to look for the magic number.
    673         *
    674         * @return an IOFileFilter that accepts files containing the magic number
    675         *         at the specified offset.
    676         *
    677         * @throws IllegalArgumentException if <code>magicNumber</code> is
    678         *         <code>null</code> or the empty String, or if offset is a
    679         *         negative number.
    680         * @see MagicNumberFileFilter
    681         * @since Commons IO 2.0
    682         */
    683        public static IOFileFilter magicNumberFileFilter(String magicNumber, long offset) {
    684            return new MagicNumberFileFilter(magicNumber, offset);
    685        }
    686
    687        /**
    688         * Returns a filter that accepts files that begin with the provided magic
    689         * number.
    690         *
    691         * @param magicNumber the magic number (byte sequence) to match at the
    692         *        beginning of each file.
    693         *
    694         * @return an IOFileFilter that accepts files beginning with the provided
    695         *         magic number.
    696         *
    697         * @throws IllegalArgumentException if <code>magicNumber</code> is
    698         *         <code>null</code> or is of length zero.
    699         * @see MagicNumberFileFilter
    700         * @since Commons IO 2.0
    701         */
    702        public static IOFileFilter magicNumberFileFilter(byte[] magicNumber) {
    703            return new MagicNumberFileFilter(magicNumber);
    704        }
    705
    706        /**
    707         * Returns a filter that accepts files that contains the provided magic
    708         * number at a specified offset within the file.
    709         *
    710         * @param magicNumber the magic number (byte sequence) to match at the
    711         *        provided offset in each file.
    712         * @param offset the offset within the files to look for the magic number.
    713         *
    714         * @return an IOFileFilter that accepts files containing the magic number
    715         *         at the specified offset.
    716         *
    717         * @throws IllegalArgumentException if <code>magicNumber</code> is
    718         *         <code>null</code>, or contains no bytes, or <code>offset</code>
    719         *         is a negative number.
    720         * @see MagicNumberFileFilter
    721         * @since Commons IO 2.0
    722         */
    723        public static IOFileFilter magicNumberFileFilter(byte[] magicNumber, long offset) {
    724            return new MagicNumberFileFilter(magicNumber, offset);
    725        }
    726
    727        //-----------------------------------------------------------------------
    728        /* Constructed on demand and then cached */
    729        private static final IOFileFilter cvsFilter = notFileFilter(
    730                and(directoryFileFilter(), nameFileFilter("CVS")));
    731
    732        /* Constructed on demand and then cached */
    733        private static final IOFileFilter svnFilter = notFileFilter(
    734                and(directoryFileFilter(), nameFileFilter(".svn")));
    735
    736        /**
    737         * Decorates a filter to make it ignore CVS directories.
    738         * Passing in <code>null</code> will return a filter that accepts everything
    739         * except CVS directories.
    740         *
    741         * @param filter  the filter to decorate, null means an unrestricted filter
    742         * @return the decorated filter, never null
    743         * @since Commons IO 1.1 (method existed but had bug in 1.0)
    744         */
    745        public static IOFileFilter makeCVSAware(IOFileFilter filter) {
    746            if (filter == null) {
    747                return cvsFilter;
    748            } else {
    749                return and(filter, cvsFilter);
    750            }
    751        }
    752
    753        /**
    754         * Decorates a filter to make it ignore SVN directories.
    755         * Passing in <code>null</code> will return a filter that accepts everything
    756         * except SVN directories.
    757         *
    758         * @param filter  the filter to decorate, null means an unrestricted filter
    759         * @return the decorated filter, never null
    760         * @since Commons IO 1.1
    761         */
    762        public static IOFileFilter makeSVNAware(IOFileFilter filter) {
    763            if (filter == null) {
    764                return svnFilter;
    765            } else {
    766                return and(filter, svnFilter);
    767            }
    768        }
    769
    770        //-----------------------------------------------------------------------
    771        /**
    772         * Decorates a filter so that it only applies to directories and not to files.
    773         *
    774         * @param filter  the filter to decorate, null means an unrestricted filter
    775         * @return the decorated filter, never null
    776         * @see DirectoryFileFilter#DIRECTORY
    777         * @since Commons IO 1.3
    778         */
    779        public static IOFileFilter makeDirectoryOnly(IOFileFilter filter) {
    780            if (filter == null) {
    781                return DirectoryFileFilter.DIRECTORY;
    782            }
    783            return new AndFileFilter(DirectoryFileFilter.DIRECTORY, filter);
    784        }
    785
    786        /**
    787         * Decorates a filter so that it only applies to files and not to directories.
    788         *
    789         * @param filter  the filter to decorate, null means an unrestricted filter
    790         * @return the decorated filter, never null
    791         * @see FileFileFilter#FILE
    792         * @since Commons IO 1.3
    793         */
    794        public static IOFileFilter makeFileOnly(IOFileFilter filter) {
    795            if (filter == null) {
    796                return FileFileFilter.FILE;
    797            }
    798            return new AndFileFilter(FileFileFilter.FILE, filter);
    799        }
    800
    801    }