View Javadoc
1   /**
2    * BSD-style license; for more info see http://pmd.sourceforge.net/license.html
3    */
4   package net.sourceforge.pmd.processor;
5   
6   import java.util.LinkedList;
7   import java.util.List;
8   import java.util.concurrent.ExecutionException;
9   import java.util.concurrent.ExecutorService;
10  import java.util.concurrent.Executors;
11  import java.util.concurrent.Future;
12  
13  import net.sourceforge.pmd.PMDConfiguration;
14  import net.sourceforge.pmd.Report;
15  import net.sourceforge.pmd.RuleContext;
16  import net.sourceforge.pmd.RuleSetFactory;
17  import net.sourceforge.pmd.RuleSets;
18  import net.sourceforge.pmd.renderers.Renderer;
19  import net.sourceforge.pmd.util.datasource.DataSource;
20  
21  /**
22   * @author Romain Pelisse <belaran@gmail.com>
23   *
24   */
25  public class MultiThreadProcessor extends AbstractPMDProcessor {
26  
27  
28  	public MultiThreadProcessor(final PMDConfiguration configuration) {
29  		super(configuration);
30  	}
31  
32  	/**
33  	 * Run PMD on a list of files using multiple threads.
34  	 */
35  	public void processFiles(final RuleSetFactory ruleSetFactory, final List<DataSource> files,
36  			final RuleContext ctx, final List<Renderer> renderers) {
37  
38  		RuleSets rs = createRuleSets(ruleSetFactory);
39  		configuration.setPmdRuleSets(rs);
40  		rs.start(ctx);
41  
42  		PmdThreadFactory factory = new PmdThreadFactory(ruleSetFactory, ctx);
43  		ExecutorService executor = Executors.newFixedThreadPool(
44  				configuration.getThreads(), factory);
45  		List<Future<Report>> tasks = new LinkedList<>();
46  
47  		for (DataSource dataSource : files) {
48  			String niceFileName = filenameFrom(dataSource);
49  
50  			PmdRunnable r = new PmdRunnable(executor, configuration,
51  					dataSource, niceFileName, renderers);
52  			Future<Report> future = executor.submit(r);
53  			tasks.add(future);
54  		}
55  		executor.shutdown();
56  
57  		processReports(renderers, tasks);
58  		
59  		rs.end(ctx);
60  		super.renderReports(renderers, ctx.getReport());
61  
62  	}
63  
64  	private void processReports(final List<Renderer> renderers, List<Future<Report>> tasks) throws Error {
65  		
66  		while (!tasks.isEmpty()) {
67  			Future<Report> future = tasks.remove(0);
68  			Report report = null;
69  			try {
70  				report = future.get();
71  			} catch (InterruptedException ie) {
72  				Thread.currentThread().interrupt();
73  				future.cancel(true);
74  			} catch (ExecutionException ee) {
75  				Throwable t = ee.getCause();
76  				if (t instanceof RuntimeException) {
77  					throw (RuntimeException) t;
78  				} else if (t instanceof Error) {
79  					throw (Error) t;
80  				} else {
81  					throw new IllegalStateException(
82  							"PmdRunnable exception", t);
83  				}
84  			}
85  
86  			super.renderReports(renderers, report);
87  		}
88  	}
89  
90  }