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  			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 }