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 javax.annotation.Nonnull;
20  import javax.annotation.Nullable;
21  import javax.inject.Named;
22  
23  import java.io.File;
24  
25  import org.codehaus.plexus.util.FileUtils;
26  import org.codehaus.plexus.util.MatchPatterns;
27  import org.codehaus.plexus.util.SelectorUtils;
28  
29  /**
30   * This file selector uses a set of patterns for including/excluding
31   * files.
32   */
33  @Named(IncludeExcludeFileSelector.ROLE_HINT)
34  public class IncludeExcludeFileSelector implements FileSelector {
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          return computedExcludes.matches(name, isCaseSensitive);
66      }
67  
68      /**
69       * Sets the list of include patterns to use. All '/' and '\' characters
70       * are replaced by <code>File.separatorChar</code>, so the separator used
71       * need not match <code>File.separatorChar</code>.
72       * <p>
73       * When a pattern ends with a '/' or '\', "**" is appended.
74       *
75       * @param includes A list of include patterns.
76       *                 May be <code>null</code>, indicating that all files
77       *                 should be included. If a non-<code>null</code>
78       *                 list is given, all elements must be
79       *                 non-<code>null</code>.
80       */
81      public void setIncludes(@Nullable String[] includes) {
82          this.includes = includes;
83          if (includes == null) {
84              computedIncludes = ALL_INCLUDES;
85          } else {
86              String[] cleaned;
87              cleaned = new String[includes.length];
88              for (int i = 0; i < includes.length; i++) {
89                  cleaned[i] = asPattern(includes[i]);
90              }
91              computedIncludes = MatchPatterns.from(cleaned);
92          }
93      }
94  
95      private static @Nonnull String getCanonicalName(@Nonnull String pName) {
96          return pName.replace('/', File.separatorChar).replace('\\', File.separatorChar);
97      }
98  
99      private String asPattern(@Nonnull String pPattern) {
100         String pattern = getCanonicalName(pPattern.trim());
101         if (pattern.endsWith(File.separator)) {
102             pattern += "**";
103         }
104         return pattern;
105     }
106 
107     /**
108      * Returns the list of include patterns to use.
109      *
110      * @return A list of include patterns.
111      *         May be <code>null</code>, indicating that all files
112      *         should be included. If a non-<code>null</code>
113      *         list is given, all elements must be
114      *         non-<code>null</code>.
115      */
116     public @Nullable String[] getIncludes() {
117         return includes;
118     }
119 
120     /**
121      * Sets the list of exclude patterns to use. All '/' and '\' characters
122      * are replaced by <code>File.separatorChar</code>, so the separator used
123      * need not match <code>File.separatorChar</code>.
124      * <p>
125      * When a pattern ends with a '/' or '\', "**" is appended.
126      *
127      * @param excludes A list of exclude patterns.
128      *                 May be <code>null</code>, indicating that no files
129      *                 should be excluded. If a non-<code>null</code> list is
130      *                 given, all elements must be non-<code>null</code>.
131      */
132     public void setExcludes(@Nullable String[] excludes) {
133         this.excludes = excludes;
134         final String[] defaultExcludes = useDefaultExcludes ? FileUtils.getDefaultExcludes() : new String[] {};
135         if (excludes == null) {
136             computedExcludes = MatchPatterns.from(defaultExcludes);
137         } else {
138             String[] temp = new String[excludes.length + defaultExcludes.length];
139             for (int i = 0; i < excludes.length; i++) {
140                 temp[i] = asPattern(excludes[i]);
141             }
142 
143             if (defaultExcludes.length > 0) {
144                 System.arraycopy(defaultExcludes, 0, temp, excludes.length, defaultExcludes.length);
145             }
146             computedExcludes = MatchPatterns.from(temp);
147         }
148     }
149 
150     /**
151      * Returns the list of exclude patterns to use.
152      *
153      * @return A list of exclude patterns.
154      *         May be <code>null</code>, indicating that no files
155      *         should be excluded. If a non-<code>null</code> list is
156      *         given, all elements must be non-<code>null</code>.
157      */
158     public @Nullable String[] getExcludes() {
159         return excludes;
160     }
161 
162     /**
163      * Tests, whether the given pattern is matching the given name.
164      * @param pattern The pattern to match
165      * @param name The name to test
166      * @param isCaseSensitive Whether the pattern is case sensitive.
167      * @return True, if the pattern matches, otherwise false
168      */
169     protected boolean matchPath(@Nonnull String pattern, @Nonnull String name, boolean isCaseSensitive) {
170         return SelectorUtils.matchPath(pattern, name, isCaseSensitive);
171     }
172 
173     /**
174      * Tests whether or not a name matches against at least one include
175      * pattern.
176      *
177      * @param name The name to match. Must not be <code>null</code>.
178      * @return <code>true</code> when the name matches against at least one
179      *         include pattern, or <code>false</code> otherwise.
180      */
181     protected boolean isIncluded(@Nonnull String name) {
182         return computedIncludes.matches(name, isCaseSensitive);
183     }
184 
185     public boolean isSelected(@Nonnull FileInfo fileInfo) {
186         final String name = getCanonicalName(fileInfo.getName());
187         return isIncluded(name) && !isExcluded(name);
188     }
189 
190     /**
191      * Returns, whether the include/exclude patterns are case sensitive.
192      * @return True, if the patterns are case sensitive (default), or false.
193      */
194     public boolean isCaseSensitive() {
195         return isCaseSensitive;
196     }
197 
198     /**
199      * Sets, whether the include/exclude patterns are case sensitive.
200      * @param caseSensitive True, if the patterns are case sensitive (default), or false.
201      */
202     public void setCaseSensitive(boolean caseSensitive) {
203         isCaseSensitive = caseSensitive;
204     }
205 
206     /**
207      * Returns, whether to use the default excludes, as specified by
208      * {@link FileUtils#getDefaultExcludes()}.
209      */
210     public boolean isUseDefaultExcludes() {
211         return useDefaultExcludes;
212     }
213 
214     /**
215      * Sets, whether to use the default excludes, as specified by
216      * {@link FileUtils#getDefaultExcludes()}.
217      */
218     public void setUseDefaultExcludes(boolean pUseDefaultExcludes) {
219         useDefaultExcludes = pUseDefaultExcludes;
220         setExcludes(excludes);
221     }
222 }