pmd: fix #1037 Facing a showstopper issue in PMD Report Class

* wrapping the report listeners in a thread safe (synchronized) class
 * overtaking the listeners for each thread / report
This commit is contained in:
Andreas Dangel
2012-12-17 10:51:19 +01:00
parent 85e493d55f
commit e3708b5030
5 changed files with 65 additions and 17 deletions

View File

@ -1,6 +1,7 @@
???? ??, 2012 - 5.0.2:
Fixed bug 1026: PMD doesn't handle 'value =' in SuppressWarnings annotation
Fixed bug 1037: Facing a showstopper issue in PMD Report Class (report listeners)
Fixed bug 1043: node.getEndLine() always returns 0 (ECMAscript)
Fixed bug 1044: Unknown option: -excludemarker
Fixed bug 1047: False Positive in 'for' loops for LocalVariableCouldBeFinal in 5.0.1

View File

@ -22,15 +22,18 @@ import net.sourceforge.pmd.util.StringUtil;
public class Report {
public static Report createReport(RuleContext ctx, String fileName) {
Report report = new Report();
ctx.setReport(report);
ctx.setSourceCodeFilename(fileName);
ctx.setSourceCodeFile(new File(fileName));
return report;
}
public static Report createReport(RuleContext ctx, String fileName) {
Report report = new Report();
// overtake the listener
report.addSynchronizedListeners(ctx.getReport().getSynchronizedListeners());
ctx.setReport(report);
ctx.setSourceCodeFilename(fileName);
ctx.setSourceCodeFile(new File(fileName));
return report;
}
public static class ReadableDuration {
private final long duration;
@ -112,7 +115,7 @@ public class Report {
// Note that this and the above data structure are both being maintained for a bit
private final List<RuleViolation> violations = new ArrayList<RuleViolation>();
private final Set<Metric> metrics = new HashSet<Metric>();
private final List<ReportListener> listeners = new ArrayList<ReportListener>();
private final List<SynchronizedReportListener> listeners = new ArrayList<SynchronizedReportListener>();
private List<ProcessingError> errors;
private List<RuleConfigurationError> configErrors;
private Map<Integer, String> linesToSuppress = new HashMap<Integer, String>();
@ -164,7 +167,7 @@ public class Report {
}
public void addListener(ReportListener listener) {
listeners.add(listener);
listeners.add(new SynchronizedReportListener(listener));
}
public List<SuppressedViolation> getSuppressedRuleViolations() {
@ -266,13 +269,13 @@ public class Report {
}
public Iterator<ProcessingError> errors() {
return errors == null ? EmptyIterator.instance : errors.iterator();
return errors == null ? EmptyIterator.<ProcessingError> instance() : errors.iterator();
}
public Iterator<RuleConfigurationError> configErrors() {
return configErrors == null ? EmptyIterator.instance : errors.iterator();
return configErrors == null ? EmptyIterator.<RuleConfigurationError> instance() : configErrors.iterator();
}
public int treeSize() {
return violationTree.size();
}
@ -292,4 +295,12 @@ public class Report {
public long getElapsedTimeInMillis() {
return end - start;
}
public List<SynchronizedReportListener> getSynchronizedListeners() {
return listeners;
}
public void addSynchronizedListeners(List<SynchronizedReportListener> synchronizedListeners) {
listeners.addAll(synchronizedListeners);
}
}

View File

@ -42,10 +42,11 @@ public class RuleContext {
}
/**
* Constructor which shares attributes with the given RuleContext.
* Constructor which shares attributes and report listeners with the given RuleContext.
*/
public RuleContext(RuleContext ruleContext) {
this.attributes = ruleContext.attributes;
this.report.addSynchronizedListeners(ruleContext.getReport().getSynchronizedListeners());
}
/**

View File

@ -0,0 +1,27 @@
/**
* BSD-style license; for more info see http://pmd.sourceforge.net/license.html
*/
package net.sourceforge.pmd;
import net.sourceforge.pmd.stat.Metric;
/**
* Wraps a report listener in order to synchronize calls to it.
*/
public final class SynchronizedReportListener implements ReportListener {
private final ReportListener wrapped;
public SynchronizedReportListener(ReportListener listener) {
this.wrapped = listener;
}
public synchronized void ruleViolationAdded(RuleViolation ruleViolation) {
wrapped.ruleViolationAdded(ruleViolation);
}
public synchronized void metricAdded(Metric metric) {
wrapped.metricAdded(metric);
}
}

View File

@ -1,3 +1,6 @@
/**
* BSD-style license; for more info see http://pmd.sourceforge.net/license.html
*/
package net.sourceforge.pmd.util;
import java.util.Iterator;
@ -9,10 +12,15 @@ import java.util.Iterator;
*
* @param <T>
*/
@SuppressWarnings("rawtypes")
public class EmptyIterator<T extends Object> implements Iterator<T> {
@SuppressWarnings("rawtypes")
public static final Iterator instance = new EmptyIterator();
@SuppressWarnings("unchecked")
public static final <T extends Object> Iterator<T> instance() {
return instance;
}
private EmptyIterator() {}
@ -23,4 +31,4 @@ public class EmptyIterator<T extends Object> implements Iterator<T> {
public void remove() {
throw new UnsupportedOperationException();
}
};
}