Cleanup the RuleSetFactory so that ClassLoader is an instance field, instead of a method argument. This removes 3 wrapper methods from the API, and a bunch of internal parameter passing. Resulting API is very much simpler.

git-svn-id: https://pmd.svn.sourceforge.net/svnroot/pmd/trunk@6593 51baf565-9d33-0410-a72c-fc3788e3496d
This commit is contained in:
Ryan Gustafson
2008-10-12 10:21:18 +00:00
parent e129bed663
commit 6054ef3c1e
5 changed files with 66 additions and 96 deletions

View File

@ -314,9 +314,16 @@ The following is relatively complete list of the major changes (this may not be
API Change - Remove deprecated APIs
Removed - AccessNode.setXXX() methods, use AccessNode.setXXX(boolean) instead.
Removed - PMDException.getReason()
Removed - RuleSetFactory.createRuleSet(String,ClassLoaer), use RuleSetFactory.createRuleSets(String,ClassLoader) instead.
Removed - RuleSetFactory.createRuleSet(String,ClassLoader), use RuleSetFactory.setClassLoader(ClassLoader) and RuleSetFactory.createRuleSets(String) instead.
Removed - net.sourceforge.pmd.cpd.FileFinder use net.sourceforge.pmd.util.FileFinder instead.
API Change - RuleSetFactory
Added - RuleSetFactory.setClassLoader(ClassLoader)
Renamed - RuleSetFactory.createSingleRuleSet(String) to RuleSetFactory.createRuleSet(String);
Removed - RuleSetFactory.createRuleSets(String, ClassLoader), use RuleSetFactory.createRuleSets(String) instead.
Removed - RuleSetFactory.createSingleRuleSet(String, ClassLoader), use RuleSetFactory.createSingleRuleSet(String) instead.
Removed - RuleSetFactory.createRuleSet(InputStream, ClassLoader), use RuleSetFactory.createRuleSet(InputStream) instead.
API Change - Changes to Renderer class, and Renderer implementations
Added - Renderer.getName()
Added - Renderer.setName(String)

View File

@ -57,7 +57,7 @@ public class RuleSetFactoryTest {
assertNull("RuleSet file name not expected", rs.getFileName());
RuleSetFactory rsf = new RuleSetFactory();
rs = rsf.createSingleRuleSet("rulesets/basic.xml");
rs = rsf.createRuleSet("rulesets/basic.xml");
assertEquals("wrong RuleSet file name", rs.getFileName(), "rulesets/basic.xml");
}
@ -77,14 +77,14 @@ public class RuleSetFactoryTest {
+ System.getProperty("java.class.path"));
}
RuleSetFactory rsf = new RuleSetFactory();
RuleSet rs = rsf.createSingleRuleSet("rulesets/favorites.xml");
RuleSet rs = rsf.createRuleSet("rulesets/favorites.xml");
assertNotNull(rs.getRuleByName("WhileLoopsMustUseBraces"));
}
@Test(expected = RuleSetNotFoundException.class)
public void testRuleSetNotFound() throws RuleSetNotFoundException {
RuleSetFactory rsf = new RuleSetFactory();
rsf.createSingleRuleSet("fooooo");
rsf.createRuleSet("fooooo");
}
@Test
@ -814,7 +814,7 @@ public class RuleSetFactoryTest {
private RuleSet loadRuleSetByFileName(String ruleSetFileName) throws RuleSetNotFoundException {
RuleSetFactory rsf = new RuleSetFactory();
return rsf.createSingleRuleSet(ruleSetFileName);
return rsf.createRuleSet(ruleSetFileName);
}
private RuleSet loadRuleSet(String ruleSetXml) {

View File

@ -30,22 +30,34 @@ import org.xml.sax.SAXException;
/**
* RuleSetFactory is responsible for creating RuleSet instances from XML content.
* By default Rules will be loaded using the ClassLoader for this class, using
* the {@link RulePriority#LOW} priority, with Rule deprecation warnings off.
*/
public class RuleSetFactory {
private static final Logger LOG = Logger.getLogger(RuleSetFactory.class.getName());
private RulePriority minPriority = RulePriority.LOW;
private ClassLoader classLoader = RuleSetFactory.class.getClassLoader();
private RulePriority minimumPriority = RulePriority.LOW;
private boolean warnDeprecated = false;
/**
* Set the ClassLoader to use when loading Rules.
*
* @param classLoader The ClassLoader to use.
*/
public void setClassLoader(ClassLoader classLoader) {
this.classLoader = classLoader;
}
/**
* Set the minimum rule priority threshold for all Rules which are loaded
* from RuleSets via reference.
*
* @param minPriority The minimum priority.
* @param minimumPriority The minimum priority.
*/
public void setMinimumPriority(RulePriority minPriority) {
this.minPriority = minPriority;
public void setMinimumPriority(RulePriority minimumPriority) {
this.minimumPriority = minimumPriority;
}
/**
@ -77,30 +89,16 @@ public class RuleSetFactory {
/**
* Create a RuleSets from a list of names.
* The ClassLoader of the RuleSetFactory class is used.
* The currently configured ClassLoader is used.
*
* @param ruleSetFileNames A comma-separated list of rule set files.
* @return The new RuleSets.
* @throws RuleSetNotFoundException if unable to find a resource.
*/
public RuleSets createRuleSets(String ruleSetFileNames) throws RuleSetNotFoundException {
// Warning: This method should not be used to implement the internals of RuleSetFactory, because it does not take an explicit ClassLoader.
return createRuleSets(ruleSetFileNames, getClass().getClassLoader());
}
/**
* Create a RuleSets from a list of names with a specified ClassLoader.
*
* @param ruleSetFileNames A comma-separated list of rule set files.
* @param classLoader The ClassLoader to load Classes and resources.
* @return The new RuleSets.
* @throws RuleSetNotFoundException if unable to find a resource.
*/
public synchronized RuleSets createRuleSets(String ruleSetFileNames, ClassLoader classLoader)
throws RuleSetNotFoundException {
public synchronized RuleSets createRuleSets(String ruleSetFileNames) throws RuleSetNotFoundException {
RuleSets ruleSets = new RuleSets();
for (StringTokenizer st = new StringTokenizer(ruleSetFileNames, ","); st.hasMoreTokens();) {
RuleSet ruleSet = createSingleRuleSet(st.nextToken().trim(), classLoader);
RuleSet ruleSet = createRuleSet(st.nextToken().trim());
ruleSets.addRuleSet(ruleSet);
}
return ruleSets;
@ -108,63 +106,36 @@ public class RuleSetFactory {
/**
* Create a RuleSet from a file name resource.
* The ClassLoader of the RuleSetFactory class is used.
* The currently configured ClassLoader is used.
*
* @param ruleSetFileName The name of rule set file loaded as a resource.
* @return A new RuleSet.
* @throws RuleSetNotFoundException if unable to find a resource.
*/
public RuleSet createSingleRuleSet(String ruleSetFileName) throws RuleSetNotFoundException {
// Warning: This method should not be used to implement the internals of RuleSetFactory, because it does not take an explicit ClassLoader.
return createSingleRuleSet(ruleSetFileName, getClass().getClassLoader());
}
/**
* Create a RuleSet from a file name resource with a specified ClassLoader.
*
* @param ruleSetFileName The name of rule set file loaded as a resource.
* @param classLoader The ClassLoader to load Classes and resources.
* @return A new RuleSet.
* @throws RuleSetNotFoundException if unable to find a resource.
*/
private RuleSet createSingleRuleSet(String ruleSetFileName, ClassLoader classLoader)
throws RuleSetNotFoundException {
return parseRuleSetNode(ruleSetFileName, tryToGetStreamTo(ruleSetFileName, classLoader), classLoader);
public synchronized RuleSet createRuleSet(String ruleSetFileName) throws RuleSetNotFoundException {
return parseRuleSetNode(ruleSetFileName, tryToGetStreamTo(ruleSetFileName));
}
/**
* Create a RuleSet from an InputStream.
* The ClassLoader of the RuleSetFactory class is used.
* The currently configured ClassLoader is used.
*
* @param inputStream InputStream containing the RuleSet XML configuration.
* @return A new RuleSet.
*/
public RuleSet createRuleSet(InputStream inputStream) {
// Warning: This method should not be used to implement the internals of RuleSetFactory, because it does not take an explicit ClassLoader.
return createRuleSet(inputStream, getClass().getClassLoader());
}
/**
* Create a RuleSet from an InputStream with a specified ClassLoader.
*
* @param inputStream InputStream containing the RuleSet XML configuration.
* @param classLoader The ClassLoader to load Classes and resources.
* @return A new RuleSet.
*/
public RuleSet createRuleSet(InputStream inputStream, ClassLoader classLoader) {
return parseRuleSetNode(null, inputStream, classLoader);
return parseRuleSetNode(null, inputStream);
}
/**
* Try to load a resource with the specified class loader
*
* @param name A resource name (e.g. a RuleSet description).
* @param classLoader The ClassLoader to load Classes and resources.
* @return An InputStream to that resource.
* @throws RuleSetNotFoundException if unable to find a resource.
*/
private InputStream tryToGetStreamTo(String name, ClassLoader classLoader) throws RuleSetNotFoundException {
InputStream in = ResourceLoader.loadResourceAsStream(name, classLoader);
private InputStream tryToGetStreamTo(String name) throws RuleSetNotFoundException {
InputStream in = ResourceLoader.loadResourceAsStream(name, this.classLoader);
if (in == null) {
throw new RuleSetNotFoundException(
"Can't find resource "
@ -179,10 +150,9 @@ public class RuleSetFactory {
* Parse a ruleset node to construct a RuleSet.
*
* @param inputStream InputStream containing the RuleSet XML configuration.
* @param classLoader The ClassLoader to load Classes and resources.
* @return The new RuleSet.
*/
private RuleSet parseRuleSetNode(String fileName, InputStream inputStream, ClassLoader classLoader) {
private RuleSet parseRuleSetNode(String fileName, InputStream inputStream) {
try {
DocumentBuilder builder = DocumentBuilderFactory.newInstance().newDocumentBuilder();
Document document = builder.parse(inputStream);
@ -203,7 +173,7 @@ public class RuleSetFactory {
} else if (node.getNodeName().equals("exclude-pattern")) {
ruleSet.addExcludePattern(parseTextNode(node));
} else if (node.getNodeName().equals("rule")) {
parseRuleNode(ruleSet, node, classLoader);
parseRuleNode(ruleSet, node);
} else {
throw new IllegalArgumentException("Unexpected element <" + node.getNodeName()
+ "> encountered as child of <ruleset> element.");
@ -241,18 +211,17 @@ public class RuleSetFactory {
*
* @param ruleSet The RuleSet being constructed.
* @param ruleNode Must be a rule element node.
* @param classLoader The ClassLoader to load Classes and resources.
*/
private void parseRuleNode(RuleSet ruleSet, Node ruleNode, ClassLoader classLoader) throws ClassNotFoundException,
InstantiationException, IllegalAccessException, RuleSetNotFoundException {
private void parseRuleNode(RuleSet ruleSet, Node ruleNode) throws ClassNotFoundException, InstantiationException,
IllegalAccessException, RuleSetNotFoundException {
Element ruleElement = (Element) ruleNode;
String ref = ruleElement.getAttribute("ref");
if (ref.endsWith("xml")) {
parseRuleSetReferenceNode(ruleSet, ruleElement, ref, classLoader);
parseRuleSetReferenceNode(ruleSet, ruleElement, ref);
} else if (ref.trim().length() == 0) {
parseSingleRuleNode(ruleSet, ruleNode, classLoader);
parseSingleRuleNode(ruleSet, ruleNode);
} else {
parseRuleReferenceNode(ruleSet, ruleNode, ref, classLoader);
parseRuleReferenceNode(ruleSet, ruleNode, ref);
}
}
@ -265,9 +234,8 @@ public class RuleSetFactory {
* @param ruleSet The RuleSet being constructed.
* @param ruleElement Must be a rule element node.
* @param ref The RuleSet reference.
* @param classLoader The ClassLoader to load Classes and resources.
*/
private void parseRuleSetReferenceNode(RuleSet ruleSet, Element ruleElement, String ref, ClassLoader classLoader)
private void parseRuleSetReferenceNode(RuleSet ruleSet, Element ruleElement, String ref)
throws RuleSetNotFoundException {
RuleSetReference ruleSetReference = new RuleSetReference();
@ -283,10 +251,11 @@ public class RuleSetFactory {
}
RuleSetFactory ruleSetFactory = new RuleSetFactory();
RuleSet otherRuleSet = ruleSetFactory.createSingleRuleSet(ref, classLoader);
ruleSetFactory.setClassLoader(this.classLoader);
RuleSet otherRuleSet = ruleSetFactory.createRuleSet(ref);
for (Rule rule : otherRuleSet.getRules()) {
if (!ruleSetReference.getExcludes().contains(rule.getName())
&& rule.getPriority().compareTo(minPriority) <= 0 && !rule.isDeprecated()) {
&& rule.getPriority().compareTo(minimumPriority) <= 0 && !rule.isDeprecated()) {
RuleReference ruleReference = new RuleReference();
ruleReference.setRuleSetReference(ruleSetReference);
ruleReference.setRule(rule);
@ -301,10 +270,9 @@ public class RuleSetFactory {
*
* @param ruleSet The RuleSet being constructed.
* @param ruleNode Must be a rule element node.
* @param classLoader The ClassLoader to load Classes and resources.
*/
private void parseSingleRuleNode(RuleSet ruleSet, Node ruleNode, ClassLoader classLoader)
throws ClassNotFoundException, InstantiationException, IllegalAccessException {
private void parseSingleRuleNode(RuleSet ruleSet, Node ruleNode) throws ClassNotFoundException,
InstantiationException, IllegalAccessException {
Element ruleElement = (Element) ruleNode;
String attribute = ruleElement.getAttribute("class");
@ -395,7 +363,7 @@ public class RuleSetFactory {
}
}
}
if (rule.getPriority().compareTo(minPriority) <= 0) {
if (rule.getPriority().compareTo(minimumPriority) <= 0) {
ruleSet.addRule(rule);
}
}
@ -408,14 +376,13 @@ public class RuleSetFactory {
* @param ruleSet The RuleSet being constructed.
* @param ruleNode Must be a rule element node.
* @param ref A reference to a Rule.
* @param classLoader The ClassLoader to load Classes and resources.
*/
private void parseRuleReferenceNode(RuleSet ruleSet, Node ruleNode, String ref, ClassLoader classLoader)
throws RuleSetNotFoundException {
private void parseRuleReferenceNode(RuleSet ruleSet, Node ruleNode, String ref) throws RuleSetNotFoundException {
RuleSetFactory ruleSetFactory = new RuleSetFactory();
ruleSetFactory.setClassLoader(this.classLoader);
ExternalRuleID externalRuleID = new ExternalRuleID(ref);
RuleSet externalRuleSet = ruleSetFactory.createSingleRuleSet(externalRuleID.getFilename(), classLoader);
RuleSet externalRuleSet = ruleSetFactory.createRuleSet(externalRuleID.getFilename());
Rule externalRule = externalRuleSet.getRuleByName(externalRuleID.getRuleName());
if (externalRule == null) {
throw new IllegalArgumentException("Unable to find rule " + externalRuleID.getRuleName()
@ -478,7 +445,7 @@ public class RuleSetFactory {
}
}
if (externalRule.getPriority().compareTo(minPriority) <= 0) {
if (externalRule.getPriority().compareTo(minimumPriority) <= 0) {
ruleSet.addRule(ruleReference);
}
}
@ -536,7 +503,8 @@ public class RuleSetFactory {
rule.setProperty(propertyDescriptor, realValue);
}
} else {
PropertyDescriptor propertyDescriptor = PropertyDescriptorFactory.createPropertyDescriptor(name, description, type, delimiter, min, max, value);
PropertyDescriptor propertyDescriptor = PropertyDescriptorFactory.createPropertyDescriptor(name,
description, type, delimiter, min, max, value);
rule.definePropertyDescriptor(propertyDescriptor);
}
}

View File

@ -178,13 +178,13 @@ public class PMDTask extends Task {
private void doTask(){
ruleSetFiles = new AntTaskNameMapper(ruleSetFiles).getRuleSets();
ClassLoader cl;
ClassLoader classLoader;
if (classpath == null) {
log("Using the normal ClassLoader", Project.MSG_VERBOSE);
cl = getClass().getClassLoader();
classLoader = getClass().getClassLoader();
} else {
log("Using the AntClassLoader", Project.MSG_VERBOSE);
cl = new AntClassLoader(getProject(), classpath);
classLoader = new AntClassLoader(getProject(), classpath);
}
/*
* 'basedir' is added to the path to make sure that relative paths
@ -197,18 +197,13 @@ public class PMDTask extends Task {
extraPath = auxClasspath.toString() + File.pathSeparator + extraPath;
}
try {
cl = new ClasspathClassLoader(extraPath, cl);
classLoader = new ClasspathClassLoader(extraPath, classLoader);
} catch (IOException ioe) {
throw new BuildException(ioe.getMessage());
}
final ClassLoader classLoader = cl;
RuleSetFactory ruleSetFactory = new RuleSetFactory() {
@Override
public RuleSets createRuleSets(String ruleSetFileNames) throws RuleSetNotFoundException {
return createRuleSets(ruleSetFiles, classLoader);
}
};
RuleSetFactory ruleSetFactory = new RuleSetFactory();
ruleSetFactory.setClassLoader(classLoader);
for (Formatter formatter: formatters) {
log("Sending a report to " + formatter, Project.MSG_VERBOSE);
formatter.start(getProject().getBaseDir().toString());
@ -219,7 +214,7 @@ public class PMDTask extends Task {
RuleSets rules;
ruleSetFactory.setMinimumPriority(minPriority);
ruleSetFactory.setWarnDeprecated(true);
rules = ruleSetFactory.createRuleSets(ruleSetFiles, classLoader);
rules = ruleSetFactory.createRuleSets(ruleSetFiles);
ruleSetFactory.setWarnDeprecated(false);
logRulesUsed(rules);
} catch (RuleSetNotFoundException e) {

View File

@ -98,7 +98,7 @@ public class Benchmark {
RuleSetFactory factory = new RuleSetFactory();
if (ruleset.length() > 0) {
SimpleRuleSetNameMapper mapper = new SimpleRuleSetNameMapper(ruleset);
stress(languageVersion, factory.createSingleRuleSet(mapper.getRuleSets()), dataSources, results, debug);
stress(languageVersion, factory.createRuleSet(mapper.getRuleSets()), dataSources, results, debug);
} else {
Iterator<RuleSet> i = factory.getRegisteredRuleSets();
while (i.hasNext()) {