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.io.File;
22 import java.io.FileFilter;
23 import java.io.FileNotFoundException;
24 import java.io.FileReader;
25 import java.io.IOException;
26 import java.util.ArrayList;
27 import java.util.Arrays;
28 import java.util.Iterator;
29 import java.util.List;
30 import java.util.Objects;
31 import java.util.function.Predicate;
32
33 import org.apache.commons.io.IOUtils;
34 import org.apache.commons.io.LineIterator;
35 import org.apache.commons.lang3.StringUtils;
36 import org.apache.rat.ConfigurationException;
37 import org.apache.rat.config.exclusion.plexus.MatchPattern;
38 import org.apache.rat.config.exclusion.plexus.SelectorUtils;
39 import org.apache.rat.document.DocumentName;
40 import org.apache.rat.document.DocumentNameMatcher;
41 import org.apache.rat.utils.DefaultLog;
42 import org.apache.rat.utils.ExtendedIterator;
43 import org.apache.rat.utils.Log;
44
45 import static java.lang.String.format;
46
47
48
49
50 public final class ExclusionUtils {
51
52
53 public static final List<String> COMMENT_PREFIXES = Arrays.asList("#", "##", "//", "/**", "/*");
54
55
56 public static final String NEGATION_PREFIX = "!";
57
58
59 public static final Predicate<String> NOT_MATCH_FILTER = s -> s.startsWith(NEGATION_PREFIX);
60
61
62 public static final Predicate<String> MATCH_FILTER = NOT_MATCH_FILTER.negate();
63
64 private ExclusionUtils() {
65
66 }
67
68
69
70
71
72
73
74
75 public static Predicate<String> commentFilter(final Iterable<String> commentPrefixes) {
76 return s -> {
77 if (StringUtils.isNotBlank(s)) {
78 int i = 1;
79 while (StringUtils.isBlank(s.substring(0, i))) {
80 i++;
81 }
82 String trimmed = i > 0 ? s.substring(i - 1) : s;
83 for (String prefix : commentPrefixes) {
84 if (trimmed.startsWith(prefix)) {
85 return false;
86 }
87 }
88 return true;
89 }
90 return false;
91 };
92 }
93
94
95
96
97
98
99
100
101 public static Predicate<String> commentFilter(final String commentPrefix) {
102 return s -> {
103 if (StringUtils.isNotBlank(s)) {
104 int i = 1;
105 while (StringUtils.isBlank(s.substring(0, i))) {
106 i++;
107 }
108 String trimmed = i > 0 ? s.substring(i - 1) : s;
109 return !trimmed.startsWith(commentPrefix);
110 }
111 return false;
112 };
113 }
114
115
116
117
118
119
120
121 public static FileFilter asFileFilter(final DocumentName parent, final DocumentNameMatcher nameMatcher) {
122 return file -> {
123 DocumentName candidate = DocumentName.builder(file).setBaseName(parent.getBaseName()).build();
124 boolean result = nameMatcher.matches(candidate);
125 Log log = DefaultLog.getInstance();
126 if (log.isEnabled(Log.Level.DEBUG)) {
127 log.debug(format("FILTER TEST for %s -> %s", file, result));
128 if (!result) {
129 List< DocumentNameMatcher.DecomposeData> data = nameMatcher.decompose(candidate);
130 log.debug("Decomposition for " + candidate);
131 data.forEach(log::debug);
132 }
133 }
134 return result;
135 };
136 }
137
138
139
140
141
142
143
144
145 public static ExtendedIterator<String> asIterator(final File patternFile, final Predicate<String> commentFilters) {
146 verifyFile(patternFile);
147 Objects.requireNonNull(commentFilters, "commentFilters");
148 try {
149 return ExtendedIterator.create(IOUtils.lineIterator(new FileReader(patternFile))).filter(commentFilters);
150 } catch (FileNotFoundException e) {
151 throw new ConfigurationException(format("%s is not a valid file.", patternFile));
152 }
153 }
154
155
156
157
158
159
160
161
162 public static Iterable<String> asIterable(final File patternFile, final String commentPrefix) {
163 return asIterable(patternFile, commentFilter(commentPrefix));
164 }
165
166
167
168
169
170
171
172
173 public static Iterable<String> asIterable(final File patternFile, final Predicate<String> commentFilters) {
174 verifyFile(patternFile);
175 Objects.requireNonNull(commentFilters, "commentFilters");
176
177
178 try (FileReader reader = new FileReader(patternFile)) {
179 List<String> result = new ArrayList<>();
180 Iterator<String> iter = new LineIterator(reader) {
181 @Override
182 protected boolean isValidLine(final String line) {
183 return commentFilters.test(line);
184 }
185 };
186 iter.forEachRemaining(result::add);
187 return result;
188 } catch (IOException e) {
189 throw new ConfigurationException("Unable to read file " + patternFile, e);
190 }
191 }
192
193
194
195
196
197
198 public static boolean isHidden(final String fileName) {
199 return fileName.startsWith(".") && !(fileName.equals(".") || fileName.equals(".."));
200 }
201
202 private static void verifyFile(final File file) {
203 if (file == null || !file.exists() || !file.isFile()) {
204 throw new ConfigurationException(format("%s is not a valid file.", file));
205 }
206 }
207
208
209
210
211
212
213
214
215 public static String qualifyPattern(final DocumentName documentName, final String pattern) {
216 boolean prefix = pattern.startsWith(NEGATION_PREFIX);
217 String workingPattern = prefix ? pattern.substring(1) : pattern;
218 String normalizedPattern = SelectorUtils.extractPattern(workingPattern, documentName.getDirectorySeparator());
219
220 StringBuilder sb = new StringBuilder(prefix ? NEGATION_PREFIX : "");
221 if (SelectorUtils.isRegexPrefixedPattern(workingPattern)) {
222 sb.append(SelectorUtils.REGEX_HANDLER_PREFIX)
223 .append("\\Q").append(documentName.getBaseName())
224 .append(documentName.getDirectorySeparator())
225 .append("\\E").append(normalizedPattern)
226 .append(SelectorUtils.PATTERN_HANDLER_SUFFIX);
227 } else {
228 sb.append(documentName.getBaseDocumentName().resolve(normalizedPattern).getName());
229 }
230 return sb.toString();
231 }
232
233
234
235
236
237
238
239
240 public static String convertSeparator(final String source, final String from, final String to) {
241 if (StringUtils.isEmpty(source) || from.equals(to)) {
242 return source;
243 }
244 return String.join(to, source.split("\\Q" + from + "\\E"));
245 }
246 }