1
2
3
4 package net.sourceforge.pmd.processor;
5
6 import java.io.BufferedInputStream;
7 import java.io.IOException;
8 import java.io.InputStream;
9 import java.util.List;
10 import java.util.concurrent.Callable;
11 import java.util.concurrent.ExecutorService;
12 import java.util.logging.Level;
13 import java.util.logging.Logger;
14
15 import net.sourceforge.pmd.PMDConfiguration;
16 import net.sourceforge.pmd.PMD;
17 import net.sourceforge.pmd.PMDException;
18 import net.sourceforge.pmd.Report;
19 import net.sourceforge.pmd.RuleContext;
20 import net.sourceforge.pmd.RuleSetFactory;
21 import net.sourceforge.pmd.RuleSets;
22 import net.sourceforge.pmd.renderers.Renderer;
23 import net.sourceforge.pmd.util.datasource.DataSource;
24
25 public class PmdRunnable extends PMD implements Callable<Report> {
26
27 private static final Logger LOG = Logger.getLogger(PmdRunnable.class.getName());
28
29 private final ExecutorService executor;
30 private final DataSource dataSource;
31 private final String fileName;
32 private final List<Renderer> renderers;
33
34 public PmdRunnable(ExecutorService executor,
35 PMDConfiguration configuration, DataSource dataSource,
36 String fileName, List<Renderer> renderers) {
37 super(configuration);
38 this.executor = executor;
39 this.dataSource = dataSource;
40 this.fileName = fileName;
41 this.renderers = renderers;
42 }
43
44
45 private static void addError(Report report, Exception ex, String fileName) {
46 report.addError(
47 new Report.ProcessingError(ex.getMessage(),
48 fileName)
49 );
50 }
51
52 private void addErrorAndShutdown(Report report, Exception e, String errorMessage) {
53
54 LOG.log(Level.FINE, errorMessage, e);
55 addError(report, e, fileName);
56 executor.shutdownNow();
57 }
58
59 public Report call() {
60 PmdThread thread = (PmdThread) Thread.currentThread();
61
62 RuleContext ctx = thread.getRuleContext();
63 RuleSets rs = thread.getRuleSets(configuration.getRuleSets());
64
65 Report report = setupReport(rs, ctx, fileName);
66
67 if (LOG.isLoggable(Level.FINE)) {
68 LOG.fine("Processing " + ctx.getSourceCodeFilename());
69 }
70 for (Renderer r : renderers) {
71 r.startFileAnalysis(dataSource);
72 }
73
74 try {
75 InputStream stream = new BufferedInputStream(
76 dataSource.getInputStream());
77 ctx.setLanguageVersion(null);
78 this.getSourceCodeProcessor().processSourceCode(stream, rs, ctx);
79 } catch (PMDException pmde) {
80 if (LOG.isLoggable(Level.FINE)) {
81 LOG.log(Level.FINE, "Error while processing file: "+fileName, pmde.getCause());
82 }
83 addError(report, pmde, fileName);
84 } catch (IOException ioe) {
85 addErrorAndShutdown(report, ioe, "IOException during processing of "+ fileName );
86
87 } catch (RuntimeException re) {
88 addErrorAndShutdown(report, re,"RuntimeException during processing of " + fileName);
89 }
90 return report;
91 }
92
93 private static class PmdThread extends Thread {
94
95 public PmdThread(int id, Runnable r, RuleSetFactory ruleSetFactory,
96 RuleContext ctx) {
97 super(r, "PmdThread " + id);
98 this.id = id;
99 context = new RuleContext(ctx);
100 this.ruleSetFactory = ruleSetFactory;
101 }
102
103 private final int id;
104 private RuleContext context;
105 private RuleSets rulesets;
106 private final RuleSetFactory ruleSetFactory;
107
108 public RuleContext getRuleContext() {
109 return context;
110 }
111
112 public RuleSets getRuleSets(String rsList) {
113 if (rulesets == null) {
114 try {
115 rulesets = ruleSetFactory.createRuleSets(rsList);
116 } catch (Exception e) {
117 e.printStackTrace();
118 }
119 }
120 return rulesets;
121 }
122
123 @Override
124 public String toString() {
125 return "PmdThread " + id;
126 }
127 }
128
129 public static Thread createThread(int id, Runnable r,
130 RuleSetFactory ruleSetFactory, RuleContext ctx) {
131 return new PmdThread(id, r,ruleSetFactory, ctx);
132 }
133 }