/
FilesScanner.java
135 lines (117 loc) · 4.83 KB
/
FilesScanner.java
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
package io.jenkins.plugins.analysis.core.model;
import java.io.File;
import java.io.IOException;
import java.io.Serializable;
import java.nio.file.Files;
import java.nio.file.Path;
import org.apache.commons.lang3.StringUtils;
import edu.hm.hafner.analysis.FileReaderFactory;
import edu.hm.hafner.analysis.IssueParser;
import edu.hm.hafner.analysis.ParsingCanceledException;
import edu.hm.hafner.analysis.ParsingException;
import edu.hm.hafner.analysis.Report;
import hudson.remoting.VirtualChannel;
import jenkins.MasterToSlaveFileCallable;
import io.jenkins.plugins.analysis.core.util.FileFinder;
import io.jenkins.plugins.prism.CharsetValidation;
import io.jenkins.plugins.util.AgentFileVisitor;
/**
* Scans files that match a specified Ant files pattern for issues and aggregates the found issues into a single {@link
* Report issues} instance. This callable will be invoked on an agent so all fields and the returned issues need to
* be {@link Serializable}.
*
* @author Ullrich Hafner
* @deprecated replaced by {@link AgentFileVisitor} in plugin-util
*/
@Deprecated
public class FilesScanner extends MasterToSlaveFileCallable<Report> {
private static final long serialVersionUID = -4242755766101768715L;
private final String filePattern;
private final IssueParser parser;
private final String encoding;
private final boolean followSymbolicLinks;
/**
* Creates a new instance of {@link FilesScanner}.
*
* @param filePattern
* ant file-set pattern to scan for files to parse
* @param encoding
* encoding of the files to parse
* @param followSymbolicLinks
* if the scanner should traverse symbolic links
* @param parser
* the parser to use
*/
public FilesScanner(final String filePattern, final String encoding,
final boolean followSymbolicLinks, final IssueParser parser) {
super();
this.filePattern = filePattern;
this.parser = parser;
this.encoding = encoding;
this.followSymbolicLinks = followSymbolicLinks;
}
@Override
public Report invoke(final File workspace, final VirtualChannel channel) {
Report report = new Report();
report.logInfo("Searching for all files in '%s' that match the pattern '%s'",
workspace.getAbsolutePath(), filePattern);
String[] fileNames = new FileFinder(filePattern, StringUtils.EMPTY, followSymbolicLinks).find(workspace);
if (fileNames.length == 0) {
report.logError("No files found for pattern '%s'. Configuration error?", filePattern);
}
else {
report.logInfo("-> found %s", plural(fileNames.length, "file"));
scanFiles(workspace, fileNames, report);
}
return report;
}
private void scanFiles(final File workspace, final String[] fileNames, final Report report) {
for (String fileName : fileNames) {
Path file = workspace.toPath().resolve(fileName);
if (!Files.isReadable(file)) {
report.logError("Skipping file '%s' because Jenkins has no permission to read the file", fileName);
}
else if (isEmpty(file)) {
report.logError("Skipping file '%s' because it's empty", fileName);
}
else {
aggregateIssuesOfFile(file, report);
}
}
}
private boolean isEmpty(final Path file) {
try {
return Files.size(file) <= 0;
}
catch (IOException e) {
return true;
}
}
private void aggregateIssuesOfFile(final Path file, final Report aggregatedReport) {
try {
Report fileReport = parser.parseFile(new FileReaderFactory(file, new CharsetValidation().getCharset(encoding)));
aggregatedReport.addAll(fileReport);
aggregatedReport.setOriginReportFile(file.toString());
aggregatedReport.logInfo("Successfully parsed file %s", file);
aggregatedReport.logInfo("-> found %s (skipped %s)",
plural(fileReport.getSize(), "issue"),
plural(fileReport.getDuplicatesSize(), "duplicate"));
}
catch (ParsingException exception) {
aggregatedReport.logException(exception, "Parsing of file '%s' failed due to an exception:", file);
}
catch (ParsingCanceledException ignored) {
aggregatedReport.logInfo("Parsing of file %s has been canceled", file);
}
}
@SuppressWarnings("PMD.AvoidLiteralsInIfCondition")
private String plural(final int count, final String itemName) {
StringBuilder builder = new StringBuilder(itemName);
if (count != 1) {
builder.append('s');
}
builder.insert(0, ' ');
builder.insert(0, count);
return builder.toString();
}
}