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<>() {
107                 @Override
108                 public boolean test(final DocumentName documentName) {
109                     File file = documentName.asFile();
110                     return file.isDirectory() && ExclusionUtils.isHidden(documentName.getShortName());
111                 }
112 
113                 @Override
114                 public String toString() {
115                     return "HIDDEN_DIR";
116                 }
117             }), null
118     ),
119     /**
120      * The hidden files. Directories with names that start with {@code .}
121      */
122     HIDDEN_FILE("The hidden files. Directories with names that start with '.'",
123             null,
124             new DocumentNameMatcher("HIDDEN_FILE", new Predicate<>() {
125                 @Override
126                 public boolean test(final DocumentName documentName) {
127                     File file = documentName.asFile();
128                     return file.isFile() && ExclusionUtils.isHidden(documentName.getShortName());
129                 }
130 
131                 @Override
132                 public String toString() {
133                     return "HIDDEN_FILE";
134                 }
135             }), null
136     ),
137     /**
138      * The files and directories created by an IDEA IDE based tool.
139      */
140     IDEA("The files and directories created by an IDEA IDE based tool.",
141             Arrays.asList("**/*.iml", "**/*.ipr", "**/*.iws", "**/.idea/**"), null, null),
142     /**
143      * The {@code .DS_Store} files on Mac computers.
144      */
145     MAC("The .DS_Store files on Mac computers.",
146             Collections.singletonList("**/.DS_Store"), null, null),
147     /**
148      * The files and directories created by Gradle build system based projects.
149      */
150     GRADLE("The files and directories created by Gradle build system based projects.",
151             Arrays.asList(
152                     "**/build/**",
153                     "**/.gradle/**",
154                     "**/.kotlin/**"
155                     ), null, null),
156     /**
157      * The files and directories created by Maven build system based project.
158      */
159     MAVEN("The files and directories created by Maven build system based project.",
160             Arrays.asList(
161                     "**/target/**", //
162                     "**/cobertura.ser", //
163                     "**/MANIFEST.MF", // a MANIFEST.MF file cannot contain comment lines. In other words: It is not possible, to include a license.
164                     "**/release.properties", //
165                     "**/.repository", // Used by Jenkins when a Maven job uses a private repository that is "Local to the workspace"
166                     "**/build.log", // RAT-160: until now maven-invoker-plugin runs create a build.log that is not part of a release
167                     "**/.mvn/**", // Project configuration since Maven 3.3.1 which contains maven.config, jvm.config, extensions.xml
168                     "**/pom.xml.releaseBackup"), null, null),
169     /**
170      * The files and directories created by a Mercurial source code control based tool.
171      */
172     MERCURIAL("The files and directories created by a Mercurial source code control based tool.",
173             Arrays.asList("**/.hg/**", "**/.hgignore"), null, new HgIgnoreBuilder()),
174     /**
175      * The set of miscellaneous files generally left by editors and the like.
176      */
177     MISC("The set of miscellaneous files generally left by editors and the like.",
178             Arrays.asList("**/*~", "**/#*#", "**/.#*", "**/%*%", "**/._*"),
179             null, null),
180     /**
181      * The files and directories created by an MKS source code control based tool.
182      */
183     MKS("The files and directories created by an MKS source code control based tool.",
184             Collections.singletonList("**/project.pj"), null, null),
185     /**
186      * The files and directories created by an RCS source code control based tool.
187      */
188     RCS("The files and directories created by a RCS source code control based tool.",
189             Collections.singletonList("**/RCS/**"), null, null),
190     /**
191      * The files and directories created by a SCCS source code control based tool.
192      */
193     SCCS("The files and directories created by a SCCS source code control based tool.",
194             Collections.singletonList("**/SCCS/**"), null, null),
195     /**
196      * The files and directories created by a Serena Dimensions V10 change control system based tool.
197      */
198     SERENA_DIMENSIONS_10("The files and directories created by a Serena Dimensions V10 change control system based tool.",
199             Collections.singletonList("**/.metadata/**"), null, null),
200     /**
201      * A standard collection of generally accepted patterns to ignore.
202      */
203     // see getCollections() for loading
204     STANDARD_PATTERNS("A standard collection of generally accepted patterns to ignore.", null, null, null),
205     /**
206      * A standard collection of SCMs.
207      */
208     // see getCollections() for loading
209     STANDARD_SCMS("A standard collection of SCMs", null, null, null),
210     /**
211      * The files and directories created by a Subversion source code control based tool.
212      */
213     SUBVERSION("The files and directories created by a Subversion source code control based tool.",
214             Collections.singletonList("**/.svn/**"), null, null),
215     /**
216      * The files and directories created by a Surround SCM source code control based tool.
217      */
218     SURROUND_SCM("The files and directories created by a Surround SCM source code control based tool.",
219             Collections.singletonList("**/.MySCMServerInfo"), null, null),
220     /**
221      * The files and directories created by a Visual Source Safe source code control based tool.
222      */
223     VSS("The files and directories created by a Visual Source Safe source code control based tool.",
224             Collections.singletonList("**/vssver.scc"), null, null);
225 
226     /** The collections of patterns to be excluded. May be empty.*/
227     private final Collection<String> patterns;
228     /** A document name matcher supplier to create a document name matcher. May be null */
229     private final DocumentNameMatcher staticDocumentNameMatcher;
230     /** The AbstractFileProcessorBuilder to process the exclude file associated with this exclusion. May be {@code null}. */
231     private final AbstractFileProcessorBuilder fileProcessorBuilder;
232     /** The description of this collection */
233     private final String desc;
234 
235     StandardCollection(final String desc, final Collection<String> patterns, final DocumentNameMatcher documentNameMatcher,
236                        final AbstractFileProcessorBuilder fileProcessorBuilder) {
237         this.desc = desc;
238         this.patterns = patterns == null ? Collections.emptyList() : new HashSet<>(patterns);
239         this.staticDocumentNameMatcher = documentNameMatcher;
240         this.fileProcessorBuilder = fileProcessorBuilder;
241     }
242 
243     /**
244      * @return the description of the given collection.
245      */
246     public String desc() {
247         return desc;
248     }
249 
250     /**
251      * Handles aggregate StandardCollections (e.g. ALL) by generating the set of StandardCollection objects that
252      * comprise this StandardCollection.
253      * @return the set of StandardCollection objects that comprise this StandardCollection.
254      */
255     private Set<StandardCollection> getCollections() {
256         Set<StandardCollection> result = new HashSet<>();
257         switch (this) {
258             case ALL:
259                 for (StandardCollection sc : StandardCollection.values()) {
260                     if (sc != ALL) {
261                         result.add(sc);
262                     }
263                 }
264                 break;
265             case STANDARD_PATTERNS:
266                 result.addAll(Arrays.asList(MISC, CVS, RCS, SCCS, VSS, MKS, SUBVERSION, ARCH, BAZAAR, SURROUND_SCM, MAC,
267                         SERENA_DIMENSIONS_10, MERCURIAL, GIT, BITKEEPER, DARCS));
268                 break;
269             case STANDARD_SCMS:
270                 result.addAll(Arrays.asList(SUBVERSION, GIT, BAZAAR, MERCURIAL, CVS));
271                 break;
272 
273             default:
274                 result.add(this);
275         }
276         return result;
277     }
278 
279     /**
280      * Returns combined and deduped collection of patterns.
281      * @return the combined and deduped collection of patterns in the given collection.
282      */
283     public Set<String> patterns() {
284         Set<String> result = new HashSet<>();
285         getCollections().forEach(sc -> result.addAll(sc.patterns));
286         return result;
287     }
288 
289     /**
290      * Returns the fileProcessor if it exists.
291      *
292      * @return the fileProcessor if it exists, {@code null} otherwise.
293      */
294     public ExtendedIterator<AbstractFileProcessorBuilder> fileProcessorBuilder() {
295         List<AbstractFileProcessorBuilder> lst = new ArrayList<>();
296         for (StandardCollection sc : getCollections()) {
297             if (sc.fileProcessorBuilder != null) {
298                 lst.add(sc.fileProcessorBuilder);
299             }
300         }
301         return ExtendedIterator.create(lst.iterator());
302     }
303 
304     /**
305      * Returns the documentNameMatchSupplier if it exists.
306      *
307      * @return the documentNameMatchSupplier if it exists, {@code null} otherwise.
308      */
309     public DocumentNameMatcher staticDocumentNameMatcher() {
310         // account for cases where this has more than one supplier.
311         List<DocumentNameMatcher> lst = new ArrayList<>();
312         for (StandardCollection sc : getCollections()) {
313             if (sc.staticDocumentNameMatcher != null) {
314                 lst.add(sc.staticDocumentNameMatcher);
315             }
316         }
317         if (lst.isEmpty()) {
318             return null;
319         }
320         if (lst.size() == 1) {
321             return lst.get(0);
322         }
323 
324         return new DocumentNameMatcher(name() + " static DocumentNameMatchers",  DocumentNameMatcher.or(lst));
325     }
326 
327     /**
328      * Returns {@code true} if the collections has a document name match supplier.
329      *
330      * @return {@code true} if the collections has a document name match supplier.
331      */
332     public boolean hasStaticDocumentNameMatcher() {
333         // account for cases where this has more than one supplier.
334         for (StandardCollection sc : getCollections()) {
335             if (sc.staticDocumentNameMatcher != null) {
336                 return true;
337             }
338         }
339         return false;
340     }
341 }