View Javadoc

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