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.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  	// If we ever end up having a ReportUtil class, this method should be moved there...
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  		// unexpected exception: log and stop executor service
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 }