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