1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19 package org.apache.rat.config.exclusion;
20
21 import java.util.ArrayList;
22 import java.util.HashSet;
23 import java.util.List;
24 import java.util.Objects;
25 import java.util.Set;
26 import java.util.TreeSet;
27 import java.util.stream.Collectors;
28
29 import org.apache.rat.document.DocumentName;
30 import org.apache.rat.document.DocumentNameMatcher;
31 import org.apache.rat.utils.DefaultLog;
32 import org.apache.rat.utils.ExtendedIterator;
33
34 import static java.lang.String.format;
35
36
37
38
39
40 public class ExclusionProcessor {
41
42 private final Set<String> excludedPatterns;
43
44 private final List<DocumentNameMatcher> excludedPaths;
45
46 private final Set<String> includedPatterns;
47
48 private final List<DocumentNameMatcher> includedPaths;
49
50
51
52
53 private final Set<StandardCollection> fileProcessors;
54
55 private final Set<StandardCollection> includedCollections;
56
57 private final Set<StandardCollection> excludedCollections;
58
59 private DocumentNameMatcher lastMatcher;
60
61 private DocumentName lastMatcherBaseDir;
62
63
64
65
66 public ExclusionProcessor() {
67 excludedPatterns = new HashSet<>();
68 excludedPaths = new ArrayList<>();
69 includedPatterns = new HashSet<>();
70 includedPaths = new ArrayList<>();
71 fileProcessors = new HashSet<>();
72 includedCollections = new HashSet<>();
73 excludedCollections = new HashSet<>();
74 }
75
76
77 private void resetLastMatcher() {
78 lastMatcher = null;
79 lastMatcherBaseDir = null;
80 }
81
82
83
84
85
86
87 public ExclusionProcessor addIncludedPatterns(final Iterable<String> patterns) {
88 DefaultLog.getInstance().info(format("Including patterns: %s", String.join(", ", patterns)));
89 patterns.forEach(includedPatterns::add);
90 resetLastMatcher();
91 return this;
92 }
93
94
95
96
97
98
99 public ExclusionProcessor addIncludedMatcher(final DocumentNameMatcher matcher) {
100 if (matcher != null) {
101 includedPaths.add(matcher);
102 resetLastMatcher();
103 }
104 return this;
105 }
106
107
108
109
110
111
112 public ExclusionProcessor addFileProcessor(final StandardCollection collection) {
113 if (collection != null) {
114 DefaultLog.getInstance().info(format("Processing exclude file from %s.", collection));
115 fileProcessors.add(collection);
116 resetLastMatcher();
117 }
118 return this;
119 }
120
121
122
123
124
125
126 public ExclusionProcessor addIncludedCollection(final StandardCollection collection) {
127 if (collection != null) {
128 DefaultLog.getInstance().info(format("Including %s collection.", collection));
129 includedCollections.add(collection);
130 resetLastMatcher();
131 }
132 return this;
133 }
134
135
136
137
138
139
140 public ExclusionProcessor addExcludedPatterns(final Iterable<String> patterns) {
141 DefaultLog.getInstance().info(format("Excluding patterns: %s", String.join(", ", patterns)));
142 patterns.forEach(excludedPatterns::add);
143 resetLastMatcher();
144 return this;
145 }
146
147
148
149
150
151
152 public ExclusionProcessor addExcludedMatcher(final DocumentNameMatcher matcher) {
153 if (matcher != null) {
154 excludedPaths.add(matcher);
155 resetLastMatcher();
156 }
157 return this;
158 }
159
160
161
162
163
164
165 public ExclusionProcessor addExcludedCollection(final StandardCollection collection) {
166 if (collection != null) {
167 DefaultLog.getInstance().info(format("Excluding %s collection.", collection));
168 excludedCollections.add(collection);
169 resetLastMatcher();
170 }
171 return this;
172 }
173
174
175
176
177
178
179
180 public DocumentNameMatcher getNameMatcher(final DocumentName basedir) {
181
182
183
184 if (lastMatcher == null || !basedir.equals(lastMatcherBaseDir)) {
185 lastMatcherBaseDir = basedir;
186
187
188 final List<MatcherSet> matchers = extractFileProcessors(basedir);
189 final MatcherSet.Builder fromCommandLine = new MatcherSet.Builder();
190 DocumentName.Builder nameBuilder = DocumentName.builder(basedir).setBaseName(basedir);
191 extractPatterns(nameBuilder, fromCommandLine);
192 extractCollectionPatterns(nameBuilder, fromCommandLine);
193 extractCollectionMatchers(fromCommandLine);
194 extractPaths(fromCommandLine);
195 matchers.add(fromCommandLine.build());
196
197 lastMatcher = MatcherSet.merge(matchers).createMatcher();
198 DefaultLog.getInstance().debug(format("Created matcher set for %s%n%s", basedir.getName(),
199 lastMatcher));
200 }
201 return lastMatcher;
202 }
203
204
205
206
207
208
209 private List<MatcherSet> extractFileProcessors(final DocumentName basedir) {
210 final List<MatcherSet> fileProcessorList = new ArrayList<>();
211 for (StandardCollection sc : fileProcessors) {
212 ExtendedIterator<List<MatcherSet>> iter = sc.fileProcessorBuilder().map(builder -> builder.build(basedir));
213 if (iter.hasNext()) {
214 iter.forEachRemaining(fileProcessorList::addAll);
215 } else {
216 DefaultLog.getInstance().debug(String.format("%s does not have a fileProcessor.", sc));
217 }
218 }
219 return fileProcessorList;
220 }
221
222
223
224
225
226
227
228
229 private String preparePattern(final DocumentName documentName, final String pattern) {
230 return ExclusionUtils.qualifyPattern(documentName,
231 ExclusionUtils.convertSeparator(pattern, "/", documentName.getDirectorySeparator()));
232 }
233
234
235
236
237
238
239 private void extractPatterns(final DocumentName.Builder nameBuilder, final MatcherSet.Builder matcherBuilder) {
240 DocumentName name = nameBuilder.setName("Patterns").build();
241 if (!excludedPatterns.isEmpty()) {
242 matcherBuilder.addExcluded(name, excludedPatterns.stream()
243 .map(s -> preparePattern(name, s))
244 .collect(Collectors.toSet()));
245 }
246 if (!includedPatterns.isEmpty()) {
247 matcherBuilder.addIncluded(name, includedPatterns.stream()
248 .map(s -> preparePattern(name, s)).collect(Collectors.toSet()));
249 }
250 }
251
252
253
254
255
256
257 private void extractCollectionPatterns(final DocumentName.Builder nameBuilder, final MatcherSet.Builder matcherBuilder) {
258 final Set<String> incl = new TreeSet<>();
259 final Set<String> excl = new TreeSet<>();
260 for (StandardCollection sc : includedCollections) {
261 Set<String> patterns = sc.patterns();
262 if (patterns.isEmpty()) {
263 DefaultLog.getInstance().debug(String.format("%s does not have a defined collection for inclusion.", sc));
264 } else {
265 MatcherSet.Builder.segregateList(incl, excl, sc.patterns());
266 }
267 }
268 for (StandardCollection sc : excludedCollections) {
269 Set<String> patterns = sc.patterns();
270 if (patterns.isEmpty()) {
271 DefaultLog.getInstance().debug(String.format("%s does not have a defined collection for exclusion.", sc));
272 } else {
273 MatcherSet.Builder.segregateList(excl, incl, sc.patterns());
274 }
275 }
276 DocumentName name = nameBuilder.setName("Collections").build();
277 matcherBuilder
278 .addExcluded(name, excl.stream().map(s -> preparePattern(name.getBaseDocumentName(), s)).collect(Collectors.toSet()))
279 .addIncluded(name, incl.stream().map(s -> preparePattern(name.getBaseDocumentName(), s)).collect(Collectors.toSet()));
280 }
281
282
283
284
285
286 private void extractCollectionMatchers(final MatcherSet.Builder matcherBuilder) {
287 ExtendedIterator.create(includedCollections.iterator())
288 .map(StandardCollection::staticDocumentNameMatcher)
289 .filter(Objects::nonNull)
290 .forEachRemaining(matcherBuilder::addIncluded);
291
292 ExtendedIterator.create(excludedCollections.iterator())
293 .map(StandardCollection::staticDocumentNameMatcher)
294 .filter(Objects::nonNull)
295 .forEachRemaining(matcherBuilder::addExcluded);
296 }
297
298
299
300
301
302 private void extractPaths(final MatcherSet.Builder matcherBuilder) {
303 if (!includedPaths.isEmpty()) {
304 for (DocumentNameMatcher matcher : includedPaths) {
305 DefaultLog.getInstance().info(format("Including path matcher %s", matcher));
306 matcherBuilder.addIncluded(matcher);
307 }
308 }
309 if (!excludedPaths.isEmpty()) {
310 for (DocumentNameMatcher matcher : excludedPaths) {
311 DefaultLog.getInstance().info(format("Excluding path matcher %s", matcher));
312 matcherBuilder.addExcluded(matcher);
313 }
314 }
315 }
316
317 }