View Javadoc
1   package org.codehaus.plexus.components.io.fileselectors;
2   
3   /*
4    * Copyright 2007 The Codehaus Foundation.
5    *
6    * Licensed under the Apache License, Version 2.0 (the "License");
7    * you may not use this file except in compliance with the License.
8    * You may obtain a copy of the License at
9    *
10   *      http://www.apache.org/licenses/LICENSE-2.0
11   *
12   * Unless required by applicable law or agreed to in writing, software
13   * distributed under the License is distributed on an "AS IS" BASIS,
14   * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15   * See the License for the specific language governing permissions and
16   * limitations under the License.
17   */
18  
19  import java.io.File;
20  
21  import org.codehaus.plexus.util.FileUtils;
22  import org.codehaus.plexus.util.MatchPatterns;
23  import org.codehaus.plexus.util.SelectorUtils;
24  
25  import javax.annotation.Nonnull;
26  import javax.annotation.Nullable;
27  
28  /**
29   * This file selector uses a set of patterns for including/excluding
30   * files.
31   */
32  public class IncludeExcludeFileSelector
33      implements FileSelector
34  {
35      /**
36       * The include/exclude file selectors role-hint: "standard".
37       */
38      public static final String ROLE_HINT = "standard";
39  
40      private static final MatchPatterns ALL_INCLUDES = MatchPatterns.from( getCanonicalName( "**/*" ) );
41  
42      private static final MatchPatterns ZERO_EXCLUDES = MatchPatterns.from();
43  
44      private boolean isCaseSensitive = true;
45  
46      private boolean useDefaultExcludes = true;
47  
48      private String[] includes;
49  
50      private String[] excludes;
51  
52      private MatchPatterns computedIncludes = ALL_INCLUDES;
53  
54      private MatchPatterns computedExcludes = ZERO_EXCLUDES;
55  
56      /**
57       * Tests whether or not a name matches against at least one exclude
58       * pattern.
59       *
60       * @param name The name to match. Must not be <code>null</code>.
61       * @return <code>true</code> when the name matches against at least one
62       *         exclude pattern, or <code>false</code> otherwise.
63       */
64      protected boolean isExcluded( @Nonnull String name )
65      {
66          return computedExcludes.matches( name, isCaseSensitive );
67      }
68  
69      /**
70       * Sets the list of include patterns to use. All '/' and '\' characters
71       * are replaced by <code>File.separatorChar</code>, so the separator used
72       * need not match <code>File.separatorChar</code>.
73       * <p>
74       * When a pattern ends with a '/' or '\', "**" is appended.
75       *
76       * @param includes A list of include patterns.
77       *                 May be <code>null</code>, indicating that all files
78       *                 should be included. If a non-<code>null</code>
79       *                 list is given, all elements must be
80       *                 non-<code>null</code>.
81       */
82      public void setIncludes( @Nullable String[] includes )
83      {
84          this.includes = includes;
85          if ( includes == null )
86          {
87              computedIncludes = ALL_INCLUDES;
88          }
89          else
90          {
91              String[] cleaned;
92              cleaned = new String[includes.length];
93              for ( int i = 0; i < includes.length; i++ )
94              {
95                  cleaned[i] = asPattern( includes[i] );
96              }
97              computedIncludes = MatchPatterns.from( cleaned );
98          }
99      }
100 
101     private static @Nonnull String getCanonicalName( @Nonnull String pName )
102     {
103         return pName.replace( '/', File.separatorChar ).replace( '\\', File.separatorChar );
104     }
105 
106     private String asPattern( @Nonnull String pPattern )
107     {
108         String pattern = getCanonicalName( pPattern.trim() );
109         if ( pattern.endsWith( File.separator ) )
110         {
111             pattern += "**";
112         }
113         return pattern;
114     }
115 
116     /**
117      * Returns the list of include patterns to use.
118      *
119      * @return A list of include patterns.
120      *         May be <code>null</code>, indicating that all files
121      *         should be included. If a non-<code>null</code>
122      *         list is given, all elements must be
123      *         non-<code>null</code>.
124      */
125     public @Nullable String[] getIncludes()
126     {
127         return includes;
128     }
129 
130     /**
131      * Sets the list of exclude patterns to use. All '/' and '\' characters
132      * are replaced by <code>File.separatorChar</code>, so the separator used
133      * need not match <code>File.separatorChar</code>.
134      * <p>
135      * When a pattern ends with a '/' or '\', "**" is appended.
136      *
137      * @param excludes A list of exclude patterns.
138      *                 May be <code>null</code>, indicating that no files
139      *                 should be excluded. If a non-<code>null</code> list is
140      *                 given, all elements must be non-<code>null</code>.
141      */
142     public void setExcludes( @Nullable String[] excludes )
143     {
144         this.excludes = excludes;
145         final String[] defaultExcludes = useDefaultExcludes ? FileUtils.getDefaultExcludes() : new String[] {};
146         if ( excludes == null )
147         {
148             computedExcludes = MatchPatterns.from( defaultExcludes );
149         }
150         else
151         {
152             String[] temp = new String[excludes.length + defaultExcludes.length];
153             for ( int i = 0; i < excludes.length; i++ )
154             {
155                 temp[i] = asPattern( excludes[i] );
156             }
157 
158             if ( defaultExcludes.length > 0 )
159             {
160                 System.arraycopy( defaultExcludes, 0, temp, excludes.length, defaultExcludes.length );
161             }
162             computedExcludes = MatchPatterns.from( temp );
163 
164         }
165     }
166 
167     /**
168      * Returns the list of exclude patterns to use.
169      *
170      * @return A list of exclude patterns.
171      *         May be <code>null</code>, indicating that no files
172      *         should be excluded. If a non-<code>null</code> list is
173      *         given, all elements must be non-<code>null</code>.
174      */
175     public @Nullable String[] getExcludes()
176     {
177         return excludes;
178     }
179 
180     /**
181      * Tests, whether the given pattern is matching the given name.
182      * @param pattern The pattern to match
183      * @param name The name to test
184      * @param isCaseSensitive Whether the pattern is case sensitive.
185      * @return True, if the pattern matches, otherwise false
186      */
187     protected boolean matchPath( @Nonnull String pattern, @Nonnull String name,
188                                  boolean isCaseSensitive )
189     {
190         return SelectorUtils.matchPath( pattern, name, isCaseSensitive );
191     }
192 
193     /**
194      * Tests whether or not a name matches against at least one include
195      * pattern.
196      *
197      * @param name The name to match. Must not be <code>null</code>.
198      * @return <code>true</code> when the name matches against at least one
199      *         include pattern, or <code>false</code> otherwise.
200      */
201     protected boolean isIncluded( @Nonnull String name )
202     {
203         return computedIncludes.matches( name, isCaseSensitive );
204     }
205 
206     public boolean isSelected( @Nonnull FileInfo fileInfo )
207     {
208         final String name = getCanonicalName( fileInfo.getName() );
209         return isIncluded( name ) && !isExcluded( name );
210     }
211 
212     /**
213      * Returns, whether the include/exclude patterns are case sensitive.
214      * @return True, if the patterns are case sensitive (default), or false.
215      */
216     public boolean isCaseSensitive()
217     {
218         return isCaseSensitive;
219     }
220 
221     /**
222      * Sets, whether the include/exclude patterns are case sensitive.
223      * @param caseSensitive True, if the patterns are case sensitive (default), or false.
224      */
225     public void setCaseSensitive( boolean caseSensitive )
226     {
227         isCaseSensitive = caseSensitive;
228     }
229 
230     /**
231      * Returns, whether to use the default excludes, as specified by
232      * {@link FileUtils#getDefaultExcludes()}.
233      */
234     public boolean isUseDefaultExcludes()
235     {
236         return useDefaultExcludes;
237     }
238 
239     /**
240      * Sets, whether to use the default excludes, as specified by
241      * {@link FileUtils#getDefaultExcludes()}.
242      */
243     public void setUseDefaultExcludes( boolean pUseDefaultExcludes )
244     {
245         useDefaultExcludes = pUseDefaultExcludes;
246         setExcludes( excludes );
247     }
248 }