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 LOG.log(Level.FINE, "Error while processing file: "+fileName, pmde.getCause());
81 addError(report, pmde, fileName);
82 } catch (IOException ioe) {
83 addErrorAndShutdown(report, ioe, "IOException during processing of "+ fileName );
84
85 } catch (RuntimeException re) {
86 addErrorAndShutdown(report, re,"RuntimeException during processing of " + fileName);
87 }
88 return report;
89 }
90
91 private static class PmdThread extends Thread {
92
93 public PmdThread(int id, Runnable r, RuleSetFactory ruleSetFactory,
94 RuleContext ctx) {
95 super(r, "PmdThread " + id);
96 this.id = id;
97 context = new RuleContext(ctx);
98 this.ruleSetFactory = ruleSetFactory;
99 }
100
101 private final int id;
102 private RuleContext context;
103 private RuleSets rulesets;
104 private final RuleSetFactory ruleSetFactory;
105
106 public RuleContext getRuleContext() {
107 return context;
108 }
109
110 public RuleSets getRuleSets(String rsList) {
111 if (rulesets == null) {
112 try {
113 rulesets = ruleSetFactory.createRuleSets(rsList);
114 } catch (Exception e) {
115 e.printStackTrace();
116 }
117 }
118 return rulesets;
119 }
120
121 @Override
122 public String toString() {
123 return "PmdThread " + id;
124 }
125 }
126
127 public static Thread createThread(int id, Runnable r,
128 RuleSetFactory ruleSetFactory, RuleContext ctx) {
129 return new PmdThread(id, r,ruleSetFactory, ctx);
130 }
131 }