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  		rs.start(ctx);
    40
    41  		PmdThreadFactory factory = new PmdThreadFactory(ruleSetFactory, ctx);
    42  		ExecutorService executor = Executors.newFixedThreadPool(
    43  				configuration.getThreads(), factory);
    44  		List<Future<Report>> tasks = new LinkedList<Future<Report>>();
    45
    46  		for (DataSource dataSource : files) {
    47  			String niceFileName = filenameFrom(dataSource);
    48
    49  			PmdRunnable r = new PmdRunnable(executor, configuration,
    50  					dataSource, niceFileName, renderers);
    51  			Future<Report> future = executor.submit(r);
    52  			tasks.add(future);
    53  		}
    54  		executor.shutdown();
    55
    56  		processReports(renderers, tasks);
    57
    58  		rs.end(ctx);
    59  		super.renderReports(renderers, ctx.getReport());
    60
    61  	}
    62
    63  	private void processReports(final List<Renderer> renderers, List<Future<Report>> tasks) throws Error {
    64
    65  		while (!tasks.isEmpty()) {
    66  			Future<Report> future = tasks.remove(0);
    67  			Report report = null;
    68  			try {
    69  				report = future.get();
    70  			} catch (InterruptedException ie) {
    71  				Thread.currentThread().interrupt();
    72  				future.cancel(true);
    73  			} catch (ExecutionException ee) {
    74  				Throwable t = ee.getCause();
    75  				if (t instanceof RuntimeException) {
    76  					throw (RuntimeException) t;
    77  				} else if (t instanceof Error) {
    78  					throw (Error) t;
    79  				} else {
    80  					throw new IllegalStateException(
    81  							"PmdRunnable exception", t);
    82  				}
    83  			}
    84
    85  			super.renderReports(renderers, report);
    86  		}
    87  	}
    88
    89  }