package org.codehaus.plexus.components.io.fileselectors; /* * Copyright 2007 The Codehaus Foundation. * * Licensed 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. */ import java.io.File; import org.codehaus.plexus.util.FileUtils; import org.codehaus.plexus.util.MatchPatterns; import org.codehaus.plexus.util.SelectorUtils; import javax.annotation.Nonnull; import javax.annotation.Nullable; /** * This file selector uses a set of patterns for including/excluding * files. */ public class IncludeExcludeFileSelector implements FileSelector { /** * The include/exclude file selectors role-hint: "standard". */ public static final String ROLE_HINT = "standard"; private static final MatchPatterns ALL_INCLUDES = MatchPatterns.from( getCanonicalName( "**/*" )); private static final MatchPatterns ZERO_EXCLUDES = MatchPatterns.from( ); private boolean isCaseSensitive = true; private boolean useDefaultExcludes = true; private String[] includes; private String[] excludes; private MatchPatterns computedIncludes = ALL_INCLUDES; private MatchPatterns computedExcludes = ZERO_EXCLUDES; /** * Tests whether or not a name matches against at least one exclude * pattern. * * @param name The name to match. Must not be <code>null</code>. * @return <code>true</code> when the name matches against at least one * exclude pattern, or <code>false</code> otherwise. */ protected boolean isExcluded( @Nonnull String name ) { return computedExcludes.matches( name, isCaseSensitive ); } /** * Sets the list of include patterns to use. All '/' and '\' characters * are replaced by <code>File.separatorChar</code>, so the separator used * need not match <code>File.separatorChar</code>. * <p> * When a pattern ends with a '/' or '\', "**" is appended. * * @param includes A list of include patterns. * May be <code>null</code>, indicating that all files * should be included. If a non-<code>null</code> * list is given, all elements must be * non-<code>null</code>. */ public void setIncludes( @Nullable String[] includes ) { this.includes = includes; if ( includes == null ) { computedIncludes = ALL_INCLUDES; } else { String [] cleaned; cleaned = new String[includes.length]; for ( int i = 0; i < includes.length; i++ ) { cleaned[i] = asPattern( includes[i] ); } computedIncludes = MatchPatterns.from( cleaned ); } } private static @Nonnull String getCanonicalName( @Nonnull String pName ) { return pName.replace( '/', File.separatorChar ).replace( '\\', File.separatorChar ); } private String asPattern( @Nonnull String pPattern ) { String pattern = getCanonicalName( pPattern.trim() ); if ( pattern.endsWith( File.separator ) ) { pattern += "**"; } return pattern; } /** * Returns the list of include patterns to use. * * @return A list of include patterns. * May be <code>null</code>, indicating that all files * should be included. If a non-<code>null</code> * list is given, all elements must be * non-<code>null</code>. */ public @Nullable String[] getIncludes() { return includes; } /** * Sets the list of exclude patterns to use. All '/' and '\' characters * are replaced by <code>File.separatorChar</code>, so the separator used * need not match <code>File.separatorChar</code>. * <p> * When a pattern ends with a '/' or '\', "**" is appended. * * @param excludes A list of exclude patterns. * May be <code>null</code>, indicating that no files * should be excluded. If a non-<code>null</code> list is * given, all elements must be non-<code>null</code>. */ public void setExcludes( @Nullable String[] excludes ) { this.excludes = excludes; final String[] defaultExcludes = useDefaultExcludes ? FileUtils.getDefaultExcludes() : new String []{}; if ( excludes == null ) { computedExcludes = MatchPatterns.from( defaultExcludes); } else { String[] temp = new String[excludes.length + defaultExcludes.length]; for ( int i = 0; i < excludes.length; i++ ) { temp[i] = asPattern( excludes[i] ); } if ( defaultExcludes.length > 0 ) { System.arraycopy( defaultExcludes, 0, temp, excludes.length, defaultExcludes.length ); } computedExcludes = MatchPatterns.from( temp ); } } /** * Returns the list of exclude patterns to use. * * @return A list of exclude patterns. * May be <code>null</code>, indicating that no files * should be excluded. If a non-<code>null</code> list is * given, all elements must be non-<code>null</code>. */ public @Nullable String[] getExcludes() { return excludes; } /** * Tests, whether the given pattern is matching the given name. * @param pattern The pattern to match * @param name The name to test * @param isCaseSensitive Whether the pattern is case sensitive. * @return True, if the pattern matches, otherwise false */ protected boolean matchPath( @Nonnull String pattern, @Nonnull String name, boolean isCaseSensitive ) { return SelectorUtils.matchPath( pattern, name, isCaseSensitive ); } /** * Tests whether or not a name matches against at least one include * pattern. * * @param name The name to match. Must not be <code>null</code>. * @return <code>true</code> when the name matches against at least one * include pattern, or <code>false</code> otherwise. */ protected boolean isIncluded( @Nonnull String name ) { return computedIncludes.matches( name, isCaseSensitive ); } public boolean isSelected( @Nonnull FileInfo fileInfo ) { final String name = getCanonicalName( fileInfo.getName() ); return isIncluded( name ) && !isExcluded( name ); } /** * Returns, whether the include/exclude patterns are case sensitive. * @return True, if the patterns are case sensitive (default), or false. */ public boolean isCaseSensitive() { return isCaseSensitive; } /** * Sets, whether the include/exclude patterns are case sensitive. * @param caseSensitive True, if the patterns are case sensitive (default), or false. */ public void setCaseSensitive( boolean caseSensitive ) { isCaseSensitive = caseSensitive; } /** * Returns, whether to use the default excludes, as specified by * {@link FileUtils#getDefaultExcludes()}. */ public boolean isUseDefaultExcludes() { return useDefaultExcludes; } /** * Sets, whether to use the default excludes, as specified by * {@link FileUtils#getDefaultExcludes()}. */ public void setUseDefaultExcludes( boolean pUseDefaultExcludes ) { useDefaultExcludes = pUseDefaultExcludes; setExcludes( excludes ); } }