/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.apache.commons.io.filefilter;
import java.io.File;
import java.io.FileFilter;
import java.io.FilenameFilter;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
import java.util.Date;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
import org.apache.commons.io.IOCase;
/**
* Useful utilities for working with file filters. It provides access to all
* file filter implementations in this package so you don't have to import every
* class you use.
*
* @since 1.0
* @version $Id: FileFilterUtils.java 1307459 2012-03-30 15:11:44Z ggregory $
*/
public class FileFilterUtils {
/**
* FileFilterUtils is not normally instantiated.
*/
public FileFilterUtils() {
}
// -----------------------------------------------------------------------
/**
* <p>
* Applies an {@link IOFileFilter} to the provided {@link File} objects. The
* resulting array is a subset of the original file list that matches the
* provided filter.
* </p>
*
* <p>
* The {@link Set} returned by this method is not guaranteed to be thread
* safe.
* </p>
*
* <pre>
* Set<File> allFiles = ...
* Set<File> javaFiles = FileFilterUtils.filterSet(allFiles,
* FileFilterUtils.suffixFileFilter(".java"));
* </pre>
*
* @param filter the filter to apply to the set of files.
* @param files the array of files to apply the filter to.
*
* @return a subset of <code>files</code> that is accepted by the file
* filter.
* @throws IllegalArgumentException if the filter is {@code null} or
* <code>files</code> contains a {@code null} value.
*
* @since 2.0
*/
public static File[] filter(IOFileFilter filter, File... files) {
if (filter == null) {
throw new IllegalArgumentException("file filter is null");
}
if (files == null) {
return new File[0];
}
List<File> acceptedFiles = new ArrayList<File>();
for (File file : files) {
if (file == null) {
throw new IllegalArgumentException("file array contains null");
}
if (filter.accept(file)) {
acceptedFiles.add(file);
}
}
return acceptedFiles.toArray(new File[acceptedFiles.size()]);
}
/**
* <p>
* Applies an {@link IOFileFilter} to the provided {@link File} objects. The
* resulting array is a subset of the original file list that matches the
* provided filter.
* </p>
*
* <p>
* The {@link Set} returned by this method is not guaranteed to be thread
* safe.
* </p>
*
* <pre>
* Set<File> allFiles = ...
* Set<File> javaFiles = FileFilterUtils.filterSet(allFiles,
* FileFilterUtils.suffixFileFilter(".java"));
* </pre>
*
* @param filter the filter to apply to the set of files.
* @param files the array of files to apply the filter to.
*
* @return a subset of <code>files</code> that is accepted by the file
* filter.
* @throws IllegalArgumentException if the filter is {@code null} or
* <code>files</code> contains a {@code null} value.
*
* @since 2.0
*/
public static File[] filter(IOFileFilter filter, Iterable<File> files) {
List<File> acceptedFiles = filterList(filter, files);
return acceptedFiles.toArray(new File[acceptedFiles.size()]);
}
/**
* <p>
* Applies an {@link IOFileFilter} to the provided {@link File} objects. The
* resulting list is a subset of the original files that matches the
* provided filter.
* </p>
*
* <p>
* The {@link List} returned by this method is not guaranteed to be thread
* safe.
* </p>
*
* <pre>
* List<File> filesAndDirectories = ...
* List<File> directories = FileFilterUtils.filterList(filesAndDirectories,
* FileFilterUtils.directoryFileFilter());
* </pre>
*
* @param filter the filter to apply to each files in the list.
* @param files the collection of files to apply the filter to.
*
* @return a subset of <code>files</code> that is accepted by the file
* filter.
* @throws IllegalArgumentException if the filter is {@code null} or
* <code>files</code> contains a {@code null} value.
* @since 2.0
*/
public static List<File> filterList(IOFileFilter filter,
Iterable<File> files) {
return filter(filter, files, new ArrayList<File>());
}
/**
* <p>
* Applies an {@link IOFileFilter} to the provided {@link File} objects. The
* resulting list is a subset of the original files that matches the
* provided filter.
* </p>
*
* <p>
* The {@link List} returned by this method is not guaranteed to be thread
* safe.
* </p>
*
* <pre>
* List<File> filesAndDirectories = ...
* List<File> directories = FileFilterUtils.filterList(filesAndDirectories,
* FileFilterUtils.directoryFileFilter());
* </pre>
*
* @param filter the filter to apply to each files in the list.
* @param files the collection of files to apply the filter to.
*
* @return a subset of <code>files</code> that is accepted by the file
* filter.
* @throws IllegalArgumentException if the filter is {@code null} or
* <code>files</code> contains a {@code null} value.
* @since 2.0
*/
public static List<File> filterList(IOFileFilter filter, File... files) {
File[] acceptedFiles = filter(filter, files);
return Arrays.asList(acceptedFiles);
}
/**
* <p>
* Applies an {@link IOFileFilter} to the provided {@link File} objects. The
* resulting set is a subset of the original file list that matches the
* provided filter.
* </p>
*
* <p>
* The {@link Set} returned by this method is not guaranteed to be thread
* safe.
* </p>
*
* <pre>
* Set<File> allFiles = ...
* Set<File> javaFiles = FileFilterUtils.filterSet(allFiles,
* FileFilterUtils.suffixFileFilter(".java"));
* </pre>
*
* @param filter the filter to apply to the set of files.
* @param files the collection of files to apply the filter to.
*
* @return a subset of <code>files</code> that is accepted by the file
* filter.
* @throws IllegalArgumentException if the filter is {@code null} or
* <code>files</code> contains a {@code null} value.
*
* @since 2.0
*/
public static Set<File> filterSet(IOFileFilter filter, File... files) {
File[] acceptedFiles = filter(filter, files);
return new HashSet<File>(Arrays.asList(acceptedFiles));
}
/**
* <p>
* Applies an {@link IOFileFilter} to the provided {@link File} objects. The
* resulting set is a subset of the original file list that matches the
* provided filter.
* </p>
*
* <p>
* The {@link Set} returned by this method is not guaranteed to be thread
* safe.
* </p>
*
* <pre>
* Set<File> allFiles = ...
* Set<File> javaFiles = FileFilterUtils.filterSet(allFiles,
* FileFilterUtils.suffixFileFilter(".java"));
* </pre>
*
* @param filter the filter to apply to the set of files.
* @param files the collection of files to apply the filter to.
*
* @return a subset of <code>files</code> that is accepted by the file
* filter.
* @throws IllegalArgumentException if the filter is {@code null} or
* <code>files</code> contains a {@code null} value.
*
* @since 2.0
*/
public static Set<File> filterSet(IOFileFilter filter, Iterable<File> files) {
return filter(filter, files, new HashSet<File>());
}
/**
* <p>
* Applies an {@link IOFileFilter} to the provided {@link File} objects and
* appends the accepted files to the other supplied collection.
* </p>
*
* <pre>
* List<File> files = ...
* List<File> directories = FileFilterUtils.filterList(files,
* FileFilterUtils.sizeFileFilter(FileUtils.FIFTY_MB),
* new ArrayList<File>());
* </pre>
*
* @param filter the filter to apply to the collection of files.
* @param files the collection of files to apply the filter to.
* @param acceptedFiles the list of files to add accepted files to.
*
* @param <T> the type of the file collection.
* @return a subset of <code>files</code> that is accepted by the file
* filter.
* @throws IllegalArgumentException if the filter is {@code null} or
* <code>files</code> contains a {@code null} value.
*/
private static <T extends Collection<File>> T filter(IOFileFilter filter,
Iterable<File> files, T acceptedFiles) {
if (filter == null) {
throw new IllegalArgumentException("file filter is null");
}
if (files != null) {
for (File file : files) {
if (file == null) {
throw new IllegalArgumentException(
"file collection contains null");
}
if (filter.accept(file)) {
acceptedFiles.add(file);
}
}
}
return acceptedFiles;
}
/**
* Returns a filter that returns true if the filename starts with the
* specified text.
*
* @param prefix the filename prefix
* @return a prefix checking filter
* @see PrefixFileFilter
*/
public static IOFileFilter prefixFileFilter(String prefix) {
return new PrefixFileFilter(prefix);
}
/**
* Returns a filter that returns true if the filename starts with the
* specified text.
*
* @param prefix the filename prefix
* @param caseSensitivity how to handle case sensitivity, null means
* case-sensitive
* @return a prefix checking filter
* @see PrefixFileFilter
* @since 2.0
*/
public static IOFileFilter prefixFileFilter(String prefix,
IOCase caseSensitivity) {
return new PrefixFileFilter(prefix, caseSensitivity);
}
/**
* Returns a filter that returns true if the filename ends with the
* specified text.
*
* @param suffix the filename suffix
* @return a suffix checking filter
* @see SuffixFileFilter
*/
public static IOFileFilter suffixFileFilter(String suffix) {
return new SuffixFileFilter(suffix);
}
/**
* Returns a filter that returns true if the filename ends with the
* specified text.
*
* @param suffix the filename suffix
* @param caseSensitivity how to handle case sensitivity, null means
* case-sensitive
* @return a suffix checking filter
* @see SuffixFileFilter
* @since 2.0
*/
public static IOFileFilter suffixFileFilter(String suffix,
IOCase caseSensitivity) {
return new SuffixFileFilter(suffix, caseSensitivity);
}
/**
* Returns a filter that returns true if the filename matches the specified
* text.
*
* @param name the filename
* @return a name checking filter
* @see NameFileFilter
*/
public static IOFileFilter nameFileFilter(String name) {
return new NameFileFilter(name);
}
/**
* Returns a filter that returns true if the filename matches the specified
* text.
*
* @param name the filename
* @param caseSensitivity how to handle case sensitivity, null means
* case-sensitive
* @return a name checking filter
* @see NameFileFilter
* @since 2.0
*/
public static IOFileFilter nameFileFilter(String name,
IOCase caseSensitivity) {
return new NameFileFilter(name, caseSensitivity);
}
/**
* Returns a filter that checks if the file is a directory.
*
* @return file filter that accepts only directories and not files
* @see DirectoryFileFilter#DIRECTORY
*/
public static IOFileFilter directoryFileFilter() {
return DirectoryFileFilter.DIRECTORY;
}
/**
* Returns a filter that checks if the file is a file (and not a directory).
*
* @return file filter that accepts only files and not directories
* @see FileFileFilter#FILE
*/
public static IOFileFilter fileFileFilter() {
return FileFileFilter.FILE;
}
// -----------------------------------------------------------------------
/**
* Returns a filter that ANDs the two specified filters.
*
* @param filter1 the first filter
* @param filter2 the second filter
* @return a filter that ANDs the two specified filters
* @see #and(IOFileFilter...)
* @see AndFileFilter
* @deprecated use {@link #and(IOFileFilter...)}
*/
@Deprecated
public static IOFileFilter andFileFilter(IOFileFilter filter1,
IOFileFilter filter2) {
return new AndFileFilter(filter1, filter2);
}
/**
* Returns a filter that ORs the two specified filters.
*
* @param filter1 the first filter
* @param filter2 the second filter
* @return a filter that ORs the two specified filters
* @see #or(IOFileFilter...)
* @see OrFileFilter
* @deprecated use {@link #or(IOFileFilter...)}
*/
@Deprecated
public static IOFileFilter orFileFilter(IOFileFilter filter1,
IOFileFilter filter2) {
return new OrFileFilter(filter1, filter2);
}
/**
* Returns a filter that ANDs the specified filters.
*
* @param filters the IOFileFilters that will be ANDed together.
* @return a filter that ANDs the specified filters
*
* @throws IllegalArgumentException if the filters are null or contain a
* null value.
* @see AndFileFilter
* @since 2.0
*/
public static IOFileFilter and(IOFileFilter... filters) {
return new AndFileFilter(toList(filters));
}
/**
* Returns a filter that ORs the specified filters.
*
* @param filters the IOFileFilters that will be ORed together.
* @return a filter that ORs the specified filters
*
* @throws IllegalArgumentException if the filters are null or contain a
* null value.
* @see OrFileFilter
* @since 2.0
*/
public static IOFileFilter or(IOFileFilter... filters) {
return new OrFileFilter(toList(filters));
}
/**
* Create a List of file filters.
*
* @param filters The file filters
* @return The list of file filters
* @throws IllegalArgumentException if the filters are null or contain a
* null value.
* @since 2.0
*/
public static List<IOFileFilter> toList(IOFileFilter... filters) {
if (filters == null) {
throw new IllegalArgumentException("The filters must not be null");
}
List<IOFileFilter> list = new ArrayList<IOFileFilter>(filters.length);
for (int i = 0; i < filters.length; i++) {
if (filters[i] == null) {
throw new IllegalArgumentException("The filter[" + i
+ "] is null");
}
list.add(filters[i]);
}
return list;
}
/**
* Returns a filter that NOTs the specified filter.
*
* @param filter the filter to invert
* @return a filter that NOTs the specified filter
* @see NotFileFilter
*/
public static IOFileFilter notFileFilter(IOFileFilter filter) {
return new NotFileFilter(filter);
}
// -----------------------------------------------------------------------
/**
* Returns a filter that always returns true.
*
* @return a true filter
* @see TrueFileFilter#TRUE
*/
public static IOFileFilter trueFileFilter() {
return TrueFileFilter.TRUE;
}
/**
* Returns a filter that always returns false.
*
* @return a false filter
* @see FalseFileFilter#FALSE
*/
public static IOFileFilter falseFileFilter() {
return FalseFileFilter.FALSE;
}
// -----------------------------------------------------------------------
/**
* Returns an <code>IOFileFilter</code> that wraps the
* <code>FileFilter</code> instance.
*
* @param filter the filter to be wrapped
* @return a new filter that implements IOFileFilter
* @see DelegateFileFilter
*/
public static IOFileFilter asFileFilter(FileFilter filter) {
return new DelegateFileFilter(filter);
}
/**
* Returns an <code>IOFileFilter</code> that wraps the
* <code>FilenameFilter</code> instance.
*
* @param filter the filter to be wrapped
* @return a new filter that implements IOFileFilter
* @see DelegateFileFilter
*/
public static IOFileFilter asFileFilter(FilenameFilter filter) {
return new DelegateFileFilter(filter);
}
// -----------------------------------------------------------------------
/**
* Returns a filter that returns true if the file was last modified after
* the specified cutoff time.
*
* @param cutoff the time threshold
* @return an appropriately configured age file filter
* @see AgeFileFilter
* @since 1.2
*/
public static IOFileFilter ageFileFilter(long cutoff) {
return new AgeFileFilter(cutoff);
}
/**
* Returns a filter that filters files based on a cutoff time.
*
* @param cutoff the time threshold
* @param acceptOlder if true, older files get accepted, if false, newer
* @return an appropriately configured age file filter
* @see AgeFileFilter
* @since 1.2
*/
public static IOFileFilter ageFileFilter(long cutoff, boolean acceptOlder) {
return new AgeFileFilter(cutoff, acceptOlder);
}
/**
* Returns a filter that returns true if the file was last modified after
* the specified cutoff date.
*
* @param cutoffDate the time threshold
* @return an appropriately configured age file filter
* @see AgeFileFilter
* @since 1.2
*/
public static IOFileFilter ageFileFilter(Date cutoffDate) {
return new AgeFileFilter(cutoffDate);
}
/**
* Returns a filter that filters files based on a cutoff date.
*
* @param cutoffDate the time threshold
* @param acceptOlder if true, older files get accepted, if false, newer
* @return an appropriately configured age file filter
* @see AgeFileFilter
* @since 1.2
*/
public static IOFileFilter ageFileFilter(Date cutoffDate,
boolean acceptOlder) {
return new AgeFileFilter(cutoffDate, acceptOlder);
}
/**
* Returns a filter that returns true if the file was last modified after
* the specified reference file.
*
* @param cutoffReference the file whose last modification time is usesd as
* the threshold age of the files
* @return an appropriately configured age file filter
* @see AgeFileFilter
* @since 1.2
*/
public static IOFileFilter ageFileFilter(File cutoffReference) {
return new AgeFileFilter(cutoffReference);
}
/**
* Returns a filter that filters files based on a cutoff reference file.
*
* @param cutoffReference the file whose last modification time is usesd as
* the threshold age of the files
* @param acceptOlder if true, older files get accepted, if false, newer
* @return an appropriately configured age file filter
* @see AgeFileFilter
* @since 1.2
*/
public static IOFileFilter ageFileFilter(File cutoffReference,
boolean acceptOlder) {
return new AgeFileFilter(cutoffReference, acceptOlder);
}
// -----------------------------------------------------------------------
/**
* Returns a filter that returns true if the file is bigger than a certain
* size.
*
* @param threshold the file size threshold
* @return an appropriately configured SizeFileFilter
* @see SizeFileFilter
* @since 1.2
*/
public static IOFileFilter sizeFileFilter(long threshold) {
return new SizeFileFilter(threshold);
}
/**
* Returns a filter that filters based on file size.
*
* @param threshold the file size threshold
* @param acceptLarger if true, larger files get accepted, if false, smaller
* @return an appropriately configured SizeFileFilter
* @see SizeFileFilter
* @since 1.2
*/
public static IOFileFilter sizeFileFilter(long threshold,
boolean acceptLarger) {
return new SizeFileFilter(threshold, acceptLarger);
}
/**
* Returns a filter that accepts files whose size is >= minimum size and
* <= maximum size.
*
* @param minSizeInclusive the minimum file size (inclusive)
* @param maxSizeInclusive the maximum file size (inclusive)
* @return an appropriately configured IOFileFilter
* @see SizeFileFilter
* @since 1.3
*/
public static IOFileFilter sizeRangeFileFilter(long minSizeInclusive,
long maxSizeInclusive) {
IOFileFilter minimumFilter = new SizeFileFilter(minSizeInclusive, true);
IOFileFilter maximumFilter = new SizeFileFilter(maxSizeInclusive + 1L,
false);
return new AndFileFilter(minimumFilter, maximumFilter);
}
/**
* Returns a filter that accepts files that begin with the provided magic
* number.
*
* @param magicNumber the magic number (byte sequence) to match at the
* beginning of each file.
*
* @return an IOFileFilter that accepts files beginning with the provided
* magic number.
*
* @throws IllegalArgumentException if <code>magicNumber</code> is
* {@code null} or the empty String.
* @see MagicNumberFileFilter
* @since 2.0
*/
public static IOFileFilter magicNumberFileFilter(String magicNumber) {
return new MagicNumberFileFilter(magicNumber);
}
/**
* Returns a filter that accepts files that contains the provided magic
* number at a specified offset within the file.
*
* @param magicNumber the magic number (byte sequence) to match at the
* provided offset in each file.
* @param offset the offset within the files to look for the magic number.
*
* @return an IOFileFilter that accepts files containing the magic number at
* the specified offset.
*
* @throws IllegalArgumentException if <code>magicNumber</code> is
* {@code null} or the empty String, or if offset is a negative number.
* @see MagicNumberFileFilter
* @since 2.0
*/
public static IOFileFilter magicNumberFileFilter(String magicNumber,
long offset) {
return new MagicNumberFileFilter(magicNumber, offset);
}
/**
* Returns a filter that accepts files that begin with the provided magic
* number.
*
* @param magicNumber the magic number (byte sequence) to match at the
* beginning of each file.
*
* @return an IOFileFilter that accepts files beginning with the provided
* magic number.
*
* @throws IllegalArgumentException if <code>magicNumber</code> is
* {@code null} or is of length zero.
* @see MagicNumberFileFilter
* @since 2.0
*/
public static IOFileFilter magicNumberFileFilter(byte[] magicNumber) {
return new MagicNumberFileFilter(magicNumber);
}
/**
* Returns a filter that accepts files that contains the provided magic
* number at a specified offset within the file.
*
* @param magicNumber the magic number (byte sequence) to match at the
* provided offset in each file.
* @param offset the offset within the files to look for the magic number.
*
* @return an IOFileFilter that accepts files containing the magic number at
* the specified offset.
*
* @throws IllegalArgumentException if <code>magicNumber</code> is
* {@code null}, or contains no bytes, or <code>offset</code> is a negative
* number.
* @see MagicNumberFileFilter
* @since 2.0
*/
public static IOFileFilter magicNumberFileFilter(byte[] magicNumber,
long offset) {
return new MagicNumberFileFilter(magicNumber, offset);
}
// -----------------------------------------------------------------------
/* Constructed on demand and then cached */
private static final IOFileFilter cvsFilter = notFileFilter(and(
directoryFileFilter(), nameFileFilter("CVS")));
/* Constructed on demand and then cached */
private static final IOFileFilter svnFilter = notFileFilter(and(
directoryFileFilter(), nameFileFilter(".svn")));
/**
* Decorates a filter to make it ignore CVS directories. Passing in
* {@code null} will return a filter that accepts everything except CVS
* directories.
*
* @param filter the filter to decorate, null means an unrestricted filter
* @return the decorated filter, never null
* @since 1.1 (method existed but had bug in 1.0)
*/
public static IOFileFilter makeCVSAware(IOFileFilter filter) {
if (filter == null) {
return cvsFilter;
} else {
return and(filter, cvsFilter);
}
}
/**
* Decorates a filter to make it ignore SVN directories. Passing in
* {@code null} will return a filter that accepts everything except SVN
* directories.
*
* @param filter the filter to decorate, null means an unrestricted filter
* @return the decorated filter, never null
* @since 1.1
*/
public static IOFileFilter makeSVNAware(IOFileFilter filter) {
if (filter == null) {
return svnFilter;
} else {
return and(filter, svnFilter);
}
}
// -----------------------------------------------------------------------
/**
* Decorates a filter so that it only applies to directories and not to
* files.
*
* @param filter the filter to decorate, null means an unrestricted filter
* @return the decorated filter, never null
* @see DirectoryFileFilter#DIRECTORY
* @since 1.3
*/
public static IOFileFilter makeDirectoryOnly(IOFileFilter filter) {
if (filter == null) {
return DirectoryFileFilter.DIRECTORY;
}
return new AndFileFilter(DirectoryFileFilter.DIRECTORY, filter);
}
/**
* Decorates a filter so that it only applies to files and not to
* directories.
*
* @param filter the filter to decorate, null means an unrestricted filter
* @return the decorated filter, never null
* @see FileFileFilter#FILE
* @since 1.3
*/
public static IOFileFilter makeFileOnly(IOFileFilter filter) {
if (filter == null) {
return FileFileFilter.FILE;
}
return new AndFileFilter(FileFileFilter.FILE, filter);
}
}