View Javadoc
1   /*
2    * Licensed to the Apache Software Foundation (ASF) under one
3    * or more contributor license agreements.  See the NOTICE file
4    * distributed with this work for additional information
5    * regarding copyright ownership.  The ASF licenses this file
6    * to you under the Apache License, Version 2.0 (the
7    * "License"); you may not use this file except in compliance
8    * with the License.  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,
13   * software distributed under the License is distributed on an
14   * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
15   * KIND, either express or implied.  See the License for the
16   * specific language governing permissions and limitations
17   * under the License.
18   */
19  package org.apache.rat.config.exclusion;
20  
21  import java.io.File;
22  import java.util.ArrayList;
23  import java.util.Arrays;
24  import java.util.Collection;
25  import java.util.Collections;
26  import java.util.HashSet;
27  import java.util.List;
28  import java.util.Set;
29  import java.util.function.Predicate;
30  
31  import org.apache.rat.config.exclusion.fileProcessors.AbstractFileProcessorBuilder;
32  import org.apache.rat.config.exclusion.fileProcessors.BazaarIgnoreBuilder;
33  import org.apache.rat.config.exclusion.fileProcessors.CVSIgnoreBuilder;
34  import org.apache.rat.config.exclusion.fileProcessors.GitIgnoreBuilder;
35  import org.apache.rat.config.exclusion.fileProcessors.HgIgnoreBuilder;
36  import org.apache.rat.document.DocumentName;
37  import org.apache.rat.document.DocumentNameMatcher;
38  import org.apache.rat.utils.ExtendedIterator;
39  
40  /**
41   * Collection of standard excludes.
42   * HINT: In order to work recursively each entry is prefixed with {@code "**\/"}.
43   */
44  public enum StandardCollection {
45      /**
46       * All the standard excludes combined.
47       */
48      // see getCollections() for loading
49      ALL("All of the Standard Excludes combined.", null, null, null),
50      /**
51       * The files and directories created by an ARCH source code control based tool.
52       */
53      ARCH("The files and directories created by an ARCH source code control based tool.",
54              Collections.singletonList("**/.arch-ids/**"), null, null),
55      /**
56       * The files and directories created by a Bazaar source code control based tool.
57       */
58      BAZAAR("The files and directories created by a Bazaar source code control based tool.",
59              Arrays.asList("**/.bzr/**", "**/.bzrignore"), null, new BazaarIgnoreBuilder()),
60      /**
61       * The files and directories created by a Bitkeeper source code control based tool.
62       */
63      BITKEEPER("The files and directories created by a Bitkeeper source code control based tool.",
64              Arrays.asList("**/BitKeeper/**", "**/ChangeSet/**"), null, null),
65      /**
66       * The files and directories created by a CVS source code control based tool.
67       * @see <a href="https://www.gnu.org/software/trans-coord/manual/cvs/html_node/cvsignore.html#cvsignore">Ignoring files via cvsignore</a>
68       */
69      CVS("The files and directories created by a CVS source code control based tool.",
70              Arrays.asList("**/.cvsignore",
71                      "**/RCS/**", "**/SCCS/**", "**/CVS/**", "**/CVS.adm/**",
72                      "**/RCSLOG/**", "**/cvslog.*", "**/tags/**", "**/TAGS/**",
73                      "**/.make.state", "**/.nse_depinfo",
74                      "**/*~", "**/#*", "**/.#*", "**/,*", "**/_$*", "**/*$", "**/*.old", "**/*.bak", "**/*.BAK",
75                      "**/*.orig", "**/*.rej", "**/.del-*",
76                      "**/*.a", "**/*.old", "**/*.o", "**/*.obj", "**/*.so", "**/*.exe",
77                      "**/*.Z", "**/*.elc", "**/*.ln", "**/core"),
78              null, new CVSIgnoreBuilder()),
79      /**
80       * The files and directories created by a DARCS source code control based tool.
81       */
82      DARCS("The files and directories created by a DARCS source code control based tool.",
83              Arrays.asList("**/_darcs/**", "**/.darcsrepo/**", "**/-darcs-backup*", "**/.darcs-temp-mail"), null, null),
84      /**
85       * The files and directories created by an Eclipse IDE based tool.
86       */
87      ECLIPSE("The files and directories created by an Eclipse IDE based tool.",
88              Arrays.asList("**/.checkstyle", "**/.classpath", "**/.factorypath",
89                      "**/.project", "**/.settings/**", "**/.externalToolBuilders/**", "**/bin/**"),
90              null, null),
91      /**
92       * The files and directories created by GIT source code control to support GIT, also processes files listed in '.gitignore'
93       * and (unless RAT_NO_GIT_GLOBAL_IGNORE is specified) the global gitignore.
94       */
95      GIT("The files and directories created by GIT source code control to support GIT, also processes files listed in '.gitignore' " +
96          "and (unless RAT_NO_GIT_GLOBAL_IGNORE is specified) the global gitignore.",
97              Arrays.asList("**/.git/**", "**/.gitignore"),
98              null,
99              new GitIgnoreBuilder()
100     ),
101     /**
102      * The hidden directories. Directories with names that start with {@code .}
103      */
104     HIDDEN_DIR("The hidden directories. Directories with names that start with '.'",
105             null,
106             new DocumentNameMatcher("HIDDEN_DIR", new Predicate<DocumentName>() {
107                 @Override
108                 public boolean test(final DocumentName documentName) {
109                     File file = documentName.asFile();
110                     return file.isDirectory() && ExclusionUtils.isHidden(documentName.getShortName());
111                 }
112                 @Override
113                 public String toString() {
114                     return "HIDDEN_DIR";
115                 }
116             }), null
117     ),
118     /**
119      * The hidden files. Directories with names that start with {@code .}
120      */
121     HIDDEN_FILE("The hidden files. Directories with names that start with '.'",
122             null,
123             new DocumentNameMatcher("HIDDEN_FILE", new Predicate<DocumentName>() {
124                 @Override
125                 public boolean test(final DocumentName documentName) {
126                     File file = documentName.asFile();
127                     return file.isFile() && ExclusionUtils.isHidden(documentName.getShortName());
128                 }
129                 @Override
130                 public String toString() {
131                     return "HIDDEN_FILE";
132                 }
133             }), null
134     ),
135     /**
136      * The files and directories created by an IDEA IDE based tool.
137      */
138     IDEA("The files and directories created by an IDEA IDE based tool.",
139             Arrays.asList("**/*.iml", "**/*.ipr", "**/*.iws", "**/.idea/**"), null, null),
140     /**
141      * The {@code .DS_Store} files on Mac computers.
142      */
143     MAC("The .DS_Store files on Mac computers.",
144             Collections.singletonList("**/.DS_Store"), null, null),
145     /**
146      * The files and directories created by Gradle build system based projects.
147      */
148     GRADLE("The files and directories created by Gradle build system based projects.",
149             Arrays.asList(
150                     "**/build/**",
151                     "**/.gradle/**",
152                     "**/.kotlin/**"
153                     ), null, null),
154     /**
155      * The files and directories created by Maven build system based project.
156      */
157     MAVEN("The files and directories created by Maven build system based project.",
158             Arrays.asList(
159                     "**/target/**", //
160                     "**/cobertura.ser", //
161                     "**/MANIFEST.MF", // a MANIFEST.MF file cannot contain comment lines. In other words: It is not possible, to include a license.
162                     "**/release.properties", //
163                     "**/.repository", // Used by Jenkins when a Maven job uses a private repository that is "Local to the workspace"
164                     "**/build.log", // RAT-160: until now maven-invoker-plugin runs create a build.log that is not part of a release
165                     "**/.mvn/**", // Project configuration since Maven 3.3.1 which contains maven.config, jvm.config, extensions.xml
166                     "**/pom.xml.releaseBackup"), null, null),
167     /**
168      * The files and directories created by a Mercurial source code control based tool.
169      */
170     MERCURIAL("The files and directories created by a Mercurial source code control based tool.",
171             Arrays.asList("**/.hg/**", "**/.hgignore"), null, new HgIgnoreBuilder()),
172     /**
173      * The set of miscellaneous files generally left by editors and the like.
174      */
175     MISC("The set of miscellaneous files generally left by editors and the like.",
176             Arrays.asList("**/*~", "**/#*#", "**/.#*", "**/%*%", "**/._*"),
177             null, null),
178     /**
179      * The files and directories created by an MKS source code control based tool.
180      */
181     MKS("The files and directories created by an MKS source code control based tool.",
182             Collections.singletonList("**/project.pj"), null, null),
183     /**
184      * The files and directories created by an RCS source code control based tool.
185      */
186     RCS("The files and directories created by a RCS source code control based tool.",
187             Collections.singletonList("**/RCS/**"), null, null),
188     /**
189      * The files and directories created by a SCCS source code control based tool.
190      */
191     SCCS("The files and directories created by a SCCS source code control based tool.",
192             Collections.singletonList("**/SCCS/**"), null, null),
193     /**
194      * The files and directories created by a Serena Dimensions V10 change control system based tool.
195      */
196     SERENA_DIMENSIONS_10("The files and directories created by a Serena Dimensions V10 change control system based tool.",
197             Collections.singletonList("**/.metadata/**"), null, null),
198     /**
199      * A standard collection of generally accepted patterns to ignore.
200      */
201     // see getCollections() for loading
202     STANDARD_PATTERNS("A standard collection of generally accepted patterns to ignore.", null, null, null),
203     /**
204      * A standard collection of SCMs.
205      */
206     // see getCollections() for loading
207     STANDARD_SCMS("A standard collection of SCMs", null, null, null),
208     /**
209      * The files and directories created by a Subversion source code control based tool.
210      */
211     SUBVERSION("The files and directories created by a Subversion source code control based tool.",
212             Collections.singletonList("**/.svn/**"), null, null),
213     /**
214      * The files and directories created by a Surround SCM source code control based tool.
215      */
216     SURROUND_SCM("The files and directories created by a Surround SCM source code control based tool.",
217             Collections.singletonList("**/.MySCMServerInfo"), null, null),
218     /**
219      * The files and directories created by a Visual Source Safe source code control based tool.
220      */
221     VSS("The files and directories created by a Visual Source Safe source code control based tool.",
222             Collections.singletonList("**/vssver.scc"), null, null);
223 
224     /** The collections of patterns to be excluded. May be empty.*/
225     private final Collection<String> patterns;
226     /** A document name matcher supplier to create a document name matcher. May be null */
227     private final DocumentNameMatcher staticDocumentNameMatcher;
228     /** The AbstractFileProcessorBuilder to process the exclude file associated with this exclusion. May be {@code null}. */
229     private final AbstractFileProcessorBuilder fileProcessorBuilder;
230     /** The description of this collection */
231     private final String desc;
232 
233     StandardCollection(final String desc, final Collection<String> patterns, final DocumentNameMatcher documentNameMatcher,
234                        final AbstractFileProcessorBuilder fileProcessorBuilder) {
235         this.desc = desc;
236         this.patterns = patterns == null ? Collections.emptyList() : new HashSet<>(patterns);
237         this.staticDocumentNameMatcher = documentNameMatcher;
238         this.fileProcessorBuilder = fileProcessorBuilder;
239     }
240 
241     /**
242      * @return the description of the given collection.
243      */
244     public String desc() {
245         return desc;
246     }
247 
248     /**
249      * Handles aggregate StandardCollections (e.g. ALL) by generating the set of StandardCollection objects that
250      * comprise this StandardCollection.
251      * @return the set of StandardCollection objects that comprise this StandardCollection.
252      */
253     private Set<StandardCollection> getCollections() {
254         Set<StandardCollection> result = new HashSet<>();
255         switch (this) {
256             case ALL:
257                 for (StandardCollection sc : StandardCollection.values()) {
258                     if (sc != ALL) {
259                         result.add(sc);
260                     }
261                 }
262                 break;
263             case STANDARD_PATTERNS:
264                 result.addAll(Arrays.asList(MISC, CVS, RCS, SCCS, VSS, MKS, SUBVERSION, ARCH, BAZAAR, SURROUND_SCM, MAC,
265                         SERENA_DIMENSIONS_10, MERCURIAL, GIT, BITKEEPER, DARCS));
266                 break;
267             case STANDARD_SCMS:
268                 result.addAll(Arrays.asList(SUBVERSION, GIT, BAZAAR, MERCURIAL, CVS));
269                 break;
270 
271             default:
272                 result.add(this);
273         }
274         return result;
275     }
276 
277     /**
278      * Returns combined and deduped collection of patterns.
279      * @return the combined and deduped collection of patterns in the given collection.
280      */
281     public Set<String> patterns() {
282         Set<String> result = new HashSet<>();
283         getCollections().forEach(sc -> result.addAll(sc.patterns));
284         return result;
285     }
286 
287     /**
288      * Returns the fileProcessor if it exists.
289      *
290      * @return the fileProcessor if it exists, {@code null} otherwise.
291      */
292     public ExtendedIterator<AbstractFileProcessorBuilder> fileProcessorBuilder() {
293         List<AbstractFileProcessorBuilder> lst = new ArrayList<>();
294         for (StandardCollection sc : getCollections()) {
295             if (sc.fileProcessorBuilder != null) {
296                 lst.add(sc.fileProcessorBuilder);
297             }
298         }
299         return ExtendedIterator.create(lst.iterator());
300     }
301 
302     /**
303      * Returns the documentNameMatchSupplier if it exists.
304      *
305      * @return the documentNameMatchSupplier if it exists, {@code null} otherwise.
306      */
307     public DocumentNameMatcher staticDocumentNameMatcher() {
308         // account for cases where this has more than one supplier.
309         List<DocumentNameMatcher> lst = new ArrayList<>();
310         for (StandardCollection sc : getCollections()) {
311             if (sc.staticDocumentNameMatcher != null) {
312                 lst.add(sc.staticDocumentNameMatcher);
313             }
314         }
315         if (lst.isEmpty()) {
316             return null;
317         }
318         if (lst.size() == 1) {
319             return lst.get(0);
320         }
321 
322         return new DocumentNameMatcher(name() + " static DocumentNameMatchers",  DocumentNameMatcher.or(lst));
323     }
324 
325     /**
326      * Returns {@code true} if the collections has a document name match supplier.
327      *
328      * @return {@code true} if the collections has a document name match supplier.
329      */
330     public boolean hasStaticDocumentNameMatcher() {
331         // account for cases where this has more than one supplier.
332         for (StandardCollection sc : getCollections()) {
333             if (sc.staticDocumentNameMatcher != null) {
334                 return true;
335             }
336         }
337         return false;
338     }
339 }