-
Notifications
You must be signed in to change notification settings - Fork 2
/
PmdRunnable.java
115 lines (95 loc) · 3.93 KB
/
PmdRunnable.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
/**
* BSD-style license; for more info see http://pmd.sourceforge.net/license.html
*/
package net.sourceforge.pmd.processor;
import java.io.BufferedInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.util.List;
import java.util.concurrent.Callable;
import java.util.logging.Level;
import java.util.logging.Logger;
import net.sourceforge.pmd.PMDException;
import net.sourceforge.pmd.Report;
import net.sourceforge.pmd.RuleContext;
import net.sourceforge.pmd.RuleSets;
import net.sourceforge.pmd.SourceCodeProcessor;
import net.sourceforge.pmd.annotation.InternalApi;
import net.sourceforge.pmd.benchmark.TimeTracker;
import net.sourceforge.pmd.renderers.Renderer;
import net.sourceforge.pmd.util.datasource.DataSource;
import net.sourceforge.pmd.util.datasource.internal.LanguageAwareDataSource;
/**
*
* @deprecated Is internal API
*/
@Deprecated
@InternalApi
public class PmdRunnable implements Callable<Report> {
private static final Logger LOG = Logger.getLogger(PmdRunnable.class.getName());
private static final ThreadLocal<ThreadContext> LOCAL_THREAD_CONTEXT = new ThreadLocal<>();
private final DataSource dataSource;
private final String fileName;
private final List<Renderer> renderers;
private final RuleContext ruleContext;
private final RuleSets ruleSets;
private final SourceCodeProcessor sourceCodeProcessor;
public PmdRunnable(DataSource dataSource, String fileName, List<Renderer> renderers,
RuleContext ruleContext, RuleSets ruleSets, SourceCodeProcessor sourceCodeProcessor) {
this.ruleSets = ruleSets;
this.dataSource = dataSource;
this.fileName = fileName;
this.renderers = renderers;
this.ruleContext = ruleContext;
this.sourceCodeProcessor = sourceCodeProcessor;
}
public static void reset() {
LOCAL_THREAD_CONTEXT.remove();
}
private void addError(Report report, Exception e, String errorMessage) {
// unexpected exception: log and stop executor service
LOG.log(Level.FINE, errorMessage, e);
report.addError(new Report.ProcessingError(e, fileName));
}
@Override
public Report call() {
TimeTracker.initThread();
ThreadContext tc = LOCAL_THREAD_CONTEXT.get();
if (tc == null) {
tc = new ThreadContext(new RuleSets(ruleSets), new RuleContext(ruleContext));
LOCAL_THREAD_CONTEXT.set(tc);
}
Report report = Report.createReport(tc.ruleContext, fileName);
if (LOG.isLoggable(Level.FINE)) {
LOG.fine("Processing " + fileName);
}
for (Renderer r : renderers) {
r.startFileAnalysis(dataSource);
}
try (InputStream stream = new BufferedInputStream(dataSource.getInputStream())) {
tc.ruleContext.setLanguageVersion(null);
if (dataSource instanceof LanguageAwareDataSource) {
tc.ruleContext.setLanguageVersion(((LanguageAwareDataSource) dataSource).getLanguageVersion());
}
sourceCodeProcessor.processSourceCode(stream, tc.ruleSets, tc.ruleContext);
} catch (PMDException pmde) {
addError(report, pmde, "Error while processing file: " + fileName);
} catch (IOException ioe) {
addError(report, ioe, "IOException during processing of " + fileName);
} catch (RuntimeException re) {
addError(report, re, "RuntimeException during processing of " + fileName);
}
TimeTracker.finishThread();
// merge the sub-report into the global report (thread-safe)
ruleContext.getReport().merge(report);
return report;
}
private static class ThreadContext {
/* default */ final RuleSets ruleSets;
/* default */ final RuleContext ruleContext;
ThreadContext(RuleSets ruleSets, RuleContext ruleContext) {
this.ruleSets = ruleSets;
this.ruleContext = ruleContext;
}
}
}