diff --git a/pmd-core/src/main/java/net/sourceforge/pmd/PMD.java b/pmd-core/src/main/java/net/sourceforge/pmd/PMD.java
index fec5ae5893..31aabbdc4e 100644
--- a/pmd-core/src/main/java/net/sourceforge/pmd/PMD.java
+++ b/pmd-core/src/main/java/net/sourceforge/pmd/PMD.java
@@ -358,16 +358,18 @@ public class PMD {
// Make sure the cache is listening for analysis results
ctx.getReport().addListener(configuration.getAnalysisCache());
-
+
+ final RuleSetFactory silentFactoy = new RuleSetFactory(ruleSetFactory, false);
+
/*
* Check if multithreaded support is available. ExecutorService can also
* be disabled if threadCount is not positive, e.g. using the
* "-threads 0" command line option.
*/
if (configuration.getThreads() > 0) {
- new MultiThreadProcessor(configuration).processFiles(ruleSetFactory, files, ctx, renderers);
+ new MultiThreadProcessor(configuration).processFiles(silentFactoy, files, ctx, renderers);
} else {
- new MonoThreadProcessor(configuration).processFiles(ruleSetFactory, files, ctx, renderers);
+ new MonoThreadProcessor(configuration).processFiles(silentFactoy, files, ctx, renderers);
}
// Persist the analysis cache
diff --git a/pmd-core/src/main/java/net/sourceforge/pmd/RuleSetFactory.java b/pmd-core/src/main/java/net/sourceforge/pmd/RuleSetFactory.java
index b3fb50ec2c..db05119414 100644
--- a/pmd-core/src/main/java/net/sourceforge/pmd/RuleSetFactory.java
+++ b/pmd-core/src/main/java/net/sourceforge/pmd/RuleSetFactory.java
@@ -57,53 +57,43 @@ public class RuleSetFactory {
private static final String MESSAGE = "message";
private static final String EXTERNAL_INFO_URL = "externalInfoUrl";
- private ClassLoader classLoader = RuleSetFactory.class.getClassLoader();
- private RulePriority minimumPriority = RulePriority.LOW;
- private boolean warnDeprecated = false;
- private RuleSetFactoryCompatibility compatibilityFilter = new RuleSetFactoryCompatibility();
+ private final ClassLoader classLoader;
+ private final RulePriority minimumPriority;
+ private final boolean warnDeprecated;
+ private final RuleSetFactoryCompatibility compatibilityFilter;
- /**
- * Set the ClassLoader to use when loading Rules.
- *
- * @param classLoader The ClassLoader to use.
- */
- public void setClassLoader(ClassLoader classLoader) {
+ public RuleSetFactory() {
+ this(RuleSetFactory.class.getClassLoader(), RulePriority.LOW, false, true);
+ }
+
+ public RuleSetFactory(final ClassLoader classLoader, final RulePriority minimumPriority,
+ final boolean warnDeprecated, final boolean enableCompatibility) {
this.classLoader = classLoader;
- }
-
- /**
- * Set the minimum rule priority threshold for all Rules which are loaded
- * from RuleSets via reference.
- *
- * @param minimumPriority The minimum priority.
- */
- public void setMinimumPriority(RulePriority minimumPriority) {
this.minimumPriority = minimumPriority;
- }
-
- /**
- * Set whether warning messages should be logged for usage of deprecated
- * Rules.
- *
- * @param warnDeprecated true
to log warning messages.
- */
- public void setWarnDeprecated(boolean warnDeprecated) {
this.warnDeprecated = warnDeprecated;
+
+ if (enableCompatibility) {
+ this.compatibilityFilter = new RuleSetFactoryCompatibility();
+ } else {
+ this.compatibilityFilter = null;
+ }
}
-
+
/**
- * Disable the ruleset compatibility filter. Disabling this filter will cause
- * exception when loading a ruleset, which uses references to old/not existing rules.
+ * Constructor copying all configuration from another factory.
+ * @param factory The factory whose configuration to copy.
+ * @param warnDeprecated Whether deprecation warnings are to be produced by this factory.
*/
- public void disableCompatibilityFilter() {
- compatibilityFilter = null;
+ public RuleSetFactory(final RuleSetFactory factory, final boolean warnDeprecated) {
+ this(factory.classLoader, factory.minimumPriority,
+ warnDeprecated, factory.compatibilityFilter != null);
}
/**
* Gets the compatibility filter in order to adjust it, e.g. add additional filters.
* @return the {@link RuleSetFactoryCompatibility}
*/
- public RuleSetFactoryCompatibility getCompatibilityFilter() {
+ /* package */ RuleSetFactoryCompatibility getCompatibilityFilter() {
return compatibilityFilter;
}
@@ -143,7 +133,7 @@ public class RuleSetFactory {
* @return The new RuleSets.
* @throws RuleSetNotFoundException if unable to find a resource.
*/
- public synchronized RuleSets createRuleSets(String referenceString) throws RuleSetNotFoundException {
+ public RuleSets createRuleSets(String referenceString) throws RuleSetNotFoundException {
return createRuleSets(RuleSetReferenceId.parse(referenceString));
}
@@ -156,7 +146,7 @@ public class RuleSetFactory {
* @return The new RuleSets.
* @throws RuleSetNotFoundException if unable to find a resource.
*/
- public synchronized RuleSets createRuleSets(List ruleSetReferenceIds)
+ public RuleSets createRuleSets(List ruleSetReferenceIds)
throws RuleSetNotFoundException {
RuleSets ruleSets = new RuleSets();
for (RuleSetReferenceId ruleSetReferenceId : ruleSetReferenceIds) {
@@ -177,7 +167,7 @@ public class RuleSetFactory {
* @return A new RuleSet.
* @throws RuleSetNotFoundException if unable to find a resource.
*/
- public synchronized RuleSet createRuleSet(String referenceString) throws RuleSetNotFoundException {
+ public RuleSet createRuleSet(String referenceString) throws RuleSetNotFoundException {
List references = RuleSetReferenceId.parse(referenceString);
if (references.isEmpty()) {
throw new RuleSetNotFoundException("No RuleSetReferenceId can be parsed from the string: <"
@@ -195,11 +185,11 @@ public class RuleSetFactory {
* @return A new RuleSet.
* @throws RuleSetNotFoundException if unable to find a resource.
*/
- public synchronized RuleSet createRuleSet(RuleSetReferenceId ruleSetReferenceId) throws RuleSetNotFoundException {
+ public RuleSet createRuleSet(RuleSetReferenceId ruleSetReferenceId) throws RuleSetNotFoundException {
return createRuleSet(ruleSetReferenceId, false);
}
- private synchronized RuleSet createRuleSet(RuleSetReferenceId ruleSetReferenceId,
+ private RuleSet createRuleSet(RuleSetReferenceId ruleSetReferenceId,
boolean withDeprecatedRuleReferences) throws RuleSetNotFoundException {
return parseRuleSetNode(ruleSetReferenceId, withDeprecatedRuleReferences);
}
@@ -359,13 +349,11 @@ public class RuleSetFactory {
}
}
- RuleSetFactory ruleSetFactory = new RuleSetFactory();
- ruleSetFactory.setClassLoader(classLoader);
+ RuleSetFactory ruleSetFactory = new RuleSetFactory(this, warnDeprecated);
RuleSet otherRuleSet = ruleSetFactory.createRuleSet(RuleSetReferenceId.parse(ref).get(0));
for (Rule rule : otherRuleSet.getRules()) {
excludedRulesCheck.remove(rule.getName());
- if (!ruleSetReference.getExcludes().contains(rule.getName())
- && rule.getPriority().compareTo(minimumPriority) <= 0 && !rule.isDeprecated()) {
+ if (!ruleSetReference.getExcludes().contains(rule.getName()) && !rule.isDeprecated()) {
RuleReference ruleReference = new RuleReference();
ruleReference.setRuleSetReference(ruleSetReference);
ruleReference.setRule(rule);
@@ -530,8 +518,7 @@ public class RuleSetFactory {
return;
}
- RuleSetFactory ruleSetFactory = new RuleSetFactory();
- ruleSetFactory.setClassLoader(classLoader);
+ RuleSetFactory ruleSetFactory = new RuleSetFactory(this, warnDeprecated);
boolean isSameRuleSet = false;
RuleSetReferenceId otherRuleSetReferenceId = RuleSetReferenceId.parse(ref).get(0);
diff --git a/pmd-core/src/main/java/net/sourceforge/pmd/RulesetsFactoryUtils.java b/pmd-core/src/main/java/net/sourceforge/pmd/RulesetsFactoryUtils.java
index 7a13d8fe8f..e7ff72e315 100644
--- a/pmd-core/src/main/java/net/sourceforge/pmd/RulesetsFactoryUtils.java
+++ b/pmd-core/src/main/java/net/sourceforge/pmd/RulesetsFactoryUtils.java
@@ -27,9 +27,7 @@ public final class RulesetsFactoryUtils {
public static RuleSets getRuleSets(String rulesets, RuleSetFactory factory) {
RuleSets ruleSets = null;
try {
- factory.setWarnDeprecated(true);
ruleSets = factory.createRuleSets(rulesets);
- factory.setWarnDeprecated(false);
printRuleNamesInDebug(ruleSets);
if (ruleSets.ruleCount() == 0) {
String msg = "No rules found. Maybe you mispelled a rule name? (" + rulesets + ")";
@@ -64,13 +62,12 @@ public final class RulesetsFactoryUtils {
return ruleSets;
}
- public static RuleSetFactory getRulesetFactory(PMDConfiguration configuration) {
- RuleSetFactory ruleSetFactory = new RuleSetFactory();
- ruleSetFactory.setMinimumPriority(configuration.getMinimumPriority());
- if (!configuration.isRuleSetFactoryCompatibilityEnabled()) {
- ruleSetFactory.disableCompatibilityFilter();
- }
- return ruleSetFactory;
+ public static RuleSetFactory getRulesetFactory(final PMDConfiguration configuration) {
+ return new RuleSetFactory(
+ configuration.getClassLoader(),
+ configuration.getMinimumPriority(),
+ true,
+ configuration.isRuleSetFactoryCompatibilityEnabled());
}
/**
diff --git a/pmd-core/src/main/java/net/sourceforge/pmd/ant/internal/PMDTaskImpl.java b/pmd-core/src/main/java/net/sourceforge/pmd/ant/internal/PMDTaskImpl.java
index c758aee43e..20d133b0f6 100644
--- a/pmd-core/src/main/java/net/sourceforge/pmd/ant/internal/PMDTaskImpl.java
+++ b/pmd-core/src/main/java/net/sourceforge/pmd/ant/internal/PMDTaskImpl.java
@@ -33,6 +33,7 @@ import net.sourceforge.pmd.RuleSet;
import net.sourceforge.pmd.RuleSetFactory;
import net.sourceforge.pmd.RuleSetNotFoundException;
import net.sourceforge.pmd.RuleSets;
+import net.sourceforge.pmd.RulesetsFactoryUtils;
import net.sourceforge.pmd.ant.Formatter;
import net.sourceforge.pmd.ant.PMDTask;
import net.sourceforge.pmd.ant.SourceLanguage;
@@ -102,23 +103,15 @@ public class PMDTaskImpl {
setupClassLoader();
// Setup RuleSetFactory and validate RuleSets
- RuleSetFactory ruleSetFactory = new RuleSetFactory();
- ruleSetFactory.setClassLoader(configuration.getClassLoader());
- if (!configuration.isRuleSetFactoryCompatibilityEnabled()) {
- ruleSetFactory.disableCompatibilityFilter();
- }
+ RuleSetFactory ruleSetFactory = RulesetsFactoryUtils.getRulesetFactory(configuration);
try {
- // This is just used to validate and display rules. Each thread will
- // create its own ruleset
- ruleSetFactory.setMinimumPriority(configuration.getMinimumPriority());
- ruleSetFactory.setWarnDeprecated(true);
+ // This is just used to validate and display rules. Each thread will create its own ruleset
String ruleSets = configuration.getRuleSets();
if (StringUtil.isNotEmpty(ruleSets)) {
// Substitute env variables/properties
configuration.setRuleSets(project.replaceProperties(ruleSets));
}
RuleSets rules = ruleSetFactory.createRuleSets(configuration.getRuleSets());
- ruleSetFactory.setWarnDeprecated(false);
logRulesUsed(rules);
} catch (RuleSetNotFoundException e) {
throw new BuildException(e.getMessage(), e);
diff --git a/pmd-core/src/main/java/net/sourceforge/pmd/benchmark/Benchmarker.java b/pmd-core/src/main/java/net/sourceforge/pmd/benchmark/Benchmarker.java
index 3586451e8b..21ce4aea4c 100644
--- a/pmd-core/src/main/java/net/sourceforge/pmd/benchmark/Benchmarker.java
+++ b/pmd-core/src/main/java/net/sourceforge/pmd/benchmark/Benchmarker.java
@@ -20,6 +20,7 @@ import net.sourceforge.pmd.PMDConfiguration;
import net.sourceforge.pmd.PMDException;
import net.sourceforge.pmd.Rule;
import net.sourceforge.pmd.RuleContext;
+import net.sourceforge.pmd.RulePriority;
import net.sourceforge.pmd.RuleSet;
import net.sourceforge.pmd.RuleSetFactory;
import net.sourceforge.pmd.RuleSetNotFoundException;
diff --git a/pmd-core/src/main/java/net/sourceforge/pmd/processor/MultiThreadProcessor.java b/pmd-core/src/main/java/net/sourceforge/pmd/processor/MultiThreadProcessor.java
index 157beda4f5..980d83829a 100644
--- a/pmd-core/src/main/java/net/sourceforge/pmd/processor/MultiThreadProcessor.java
+++ b/pmd-core/src/main/java/net/sourceforge/pmd/processor/MultiThreadProcessor.java
@@ -4,7 +4,6 @@
package net.sourceforge.pmd.processor;
import java.util.ArrayList;
-import java.util.LinkedList;
import java.util.List;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.ExecutorService;
diff --git a/pmd-core/src/main/java/net/sourceforge/pmd/processor/PmdThreadFactory.java b/pmd-core/src/main/java/net/sourceforge/pmd/processor/PmdThreadFactory.java
index 1086124cb0..92d2649554 100644
--- a/pmd-core/src/main/java/net/sourceforge/pmd/processor/PmdThreadFactory.java
+++ b/pmd-core/src/main/java/net/sourceforge/pmd/processor/PmdThreadFactory.java
@@ -3,9 +3,6 @@
*/
package net.sourceforge.pmd.processor;
-import java.util.Collections;
-import java.util.LinkedList;
-import java.util.List;
import java.util.concurrent.ThreadFactory;
import java.util.concurrent.atomic.AtomicInteger;
@@ -17,7 +14,6 @@ public class PmdThreadFactory implements ThreadFactory {
private final RuleSetFactory ruleSetFactory;
private final RuleContext ctx;
private final AtomicInteger counter = new AtomicInteger();
- public List threadList = Collections.synchronizedList(new LinkedList());
public PmdThreadFactory(RuleSetFactory ruleSetFactory, RuleContext ctx) {
this.ruleSetFactory = ruleSetFactory;
@@ -27,7 +23,6 @@ public class PmdThreadFactory implements ThreadFactory {
@Override
public Thread newThread(Runnable r) {
Thread t = PmdRunnable.createThread(counter.incrementAndGet(), r, ruleSetFactory, ctx);
- threadList.add(t);
return t;
}
diff --git a/pmd-core/src/test/java/net/sourceforge/pmd/RuleSetFactoryTest.java b/pmd-core/src/test/java/net/sourceforge/pmd/RuleSetFactoryTest.java
index 412c56dbb0..0fbe28c557 100644
--- a/pmd-core/src/test/java/net/sourceforge/pmd/RuleSetFactoryTest.java
+++ b/pmd-core/src/test/java/net/sourceforge/pmd/RuleSetFactoryTest.java
@@ -342,9 +342,8 @@ public class RuleSetFactoryTest {
@Test
public void testReferencePriority() throws RuleSetNotFoundException {
- RuleSetFactory rsf = new RuleSetFactory();
+ RuleSetFactory rsf = new RuleSetFactory(getClass().getClassLoader(), RulePriority.LOW, false, true);
- rsf.setMinimumPriority(RulePriority.LOW);
RuleSet ruleSet = rsf
.createRuleSet(createRuleSetReferenceId(REF_INTERNAL_TO_INTERNAL_CHAIN));
assertEquals("Number of Rules", 3, ruleSet.getRules().size());
@@ -352,20 +351,20 @@ public class RuleSetFactoryTest {
assertNotNull(ruleSet.getRuleByName("MockRuleNameRef"));
assertNotNull(ruleSet.getRuleByName("MockRuleNameRefRef"));
- rsf.setMinimumPriority(RulePriority.MEDIUM_HIGH);
+ rsf = new RuleSetFactory(getClass().getClassLoader(), RulePriority.MEDIUM_HIGH, false, true);
ruleSet = rsf
.createRuleSet(createRuleSetReferenceId(REF_INTERNAL_TO_INTERNAL_CHAIN));
assertEquals("Number of Rules", 2, ruleSet.getRules().size());
assertNotNull(ruleSet.getRuleByName("MockRuleNameRef"));
assertNotNull(ruleSet.getRuleByName("MockRuleNameRefRef"));
- rsf.setMinimumPriority(RulePriority.HIGH);
+ rsf = new RuleSetFactory(getClass().getClassLoader(), RulePriority.HIGH, false, true);
ruleSet = rsf
.createRuleSet(createRuleSetReferenceId(REF_INTERNAL_TO_INTERNAL_CHAIN));
assertEquals("Number of Rules", 1, ruleSet.getRules().size());
assertNotNull(ruleSet.getRuleByName("MockRuleNameRefRef"));
- rsf.setMinimumPriority(RulePriority.LOW);
+ rsf = new RuleSetFactory(getClass().getClassLoader(), RulePriority.LOW, false, true);
ruleSet = rsf
.createRuleSet(createRuleSetReferenceId(REF_INTERNAL_TO_EXTERNAL_CHAIN));
assertEquals("Number of Rules", 3, ruleSet.getRules().size());
@@ -373,14 +372,14 @@ public class RuleSetFactoryTest {
assertNotNull(ruleSet.getRuleByName("ExternalRefRuleNameRef"));
assertNotNull(ruleSet.getRuleByName("ExternalRefRuleNameRefRef"));
- rsf.setMinimumPriority(RulePriority.MEDIUM_HIGH);
+ rsf = new RuleSetFactory(getClass().getClassLoader(), RulePriority.MEDIUM_HIGH, false, true);
ruleSet = rsf
.createRuleSet(createRuleSetReferenceId(REF_INTERNAL_TO_EXTERNAL_CHAIN));
assertEquals("Number of Rules", 2, ruleSet.getRules().size());
assertNotNull(ruleSet.getRuleByName("ExternalRefRuleNameRef"));
assertNotNull(ruleSet.getRuleByName("ExternalRefRuleNameRefRef"));
- rsf.setMinimumPriority(RulePriority.HIGH);
+ rsf = new RuleSetFactory(getClass().getClassLoader(), RulePriority.HIGH, false, true);
ruleSet = rsf
.createRuleSet(createRuleSetReferenceId(REF_INTERNAL_TO_EXTERNAL_CHAIN));
assertEquals("Number of Rules", 1, ruleSet.getRules().size());
@@ -407,11 +406,10 @@ public class RuleSetFactoryTest {
@Test
public void testSetPriority() throws RuleSetNotFoundException {
- RuleSetFactory rsf = new RuleSetFactory();
- rsf.setMinimumPriority(RulePriority.MEDIUM_HIGH);
+ RuleSetFactory rsf = new RuleSetFactory(getClass().getClassLoader(), RulePriority.MEDIUM_HIGH, false, true);
assertEquals(0, rsf
.createRuleSet(createRuleSetReferenceId(SINGLE_RULE)).size());
- rsf.setMinimumPriority(RulePriority.MEDIUM_LOW);
+ rsf = new RuleSetFactory(getClass().getClassLoader(), RulePriority.MEDIUM_LOW, false, true);
assertEquals(1, rsf
.createRuleSet(createRuleSetReferenceId(SINGLE_RULE)).size());
}
diff --git a/src/site/markdown/overview/changelog.md b/src/site/markdown/overview/changelog.md
index a6e8f97aa1..7cf1ed2246 100644
--- a/src/site/markdown/overview/changelog.md
+++ b/src/site/markdown/overview/changelog.md
@@ -36,6 +36,7 @@
* [#128](https://github.com/pmd/pmd/pull/128): \[java] Minor optimizations to type resolution
* [#129](https://github.com/pmd/pmd/pull/129): \[plsql] Added correct parse of IS [NOT] NULL and multiline DML
* [#130](https://github.com/pmd/pmd/pull/130); \[core] Reduce thread contention
+* [#131](https://github.com/pmd/pmd/pull/131): \[core] Make RuleSetFactory immutable
* [#135](https://github.com/pmd/pmd/pull/135): \[apex] New ruleset for Apex security
**Bugfixes:**