View Javadoc
1 package net.sourceforge.pmd; 2 3 import net.sourceforge.pmd.util.ResourceLoader; 4 import org.w3c.dom.Document; 5 import org.w3c.dom.Element; 6 import org.w3c.dom.Node; 7 import org.w3c.dom.NodeList; 8 9 import javax.xml.parsers.DocumentBuilder; 10 import javax.xml.parsers.DocumentBuilderFactory; 11 import java.io.IOException; 12 import java.io.InputStream; 13 import java.util.ArrayList; 14 import java.util.HashSet; 15 import java.util.Iterator; 16 import java.util.List; 17 import java.util.Properties; 18 import java.util.Set; 19 import java.util.StringTokenizer; 20 21 public class RuleSetFactory { 22 23 /*** 24 * Returns an Iterator of RuleSet objects 25 */ 26 public Iterator getRegisteredRuleSets() throws RuleSetNotFoundException { 27 try { 28 Properties props = new Properties(); 29 props.load(ResourceLoader.loadResourceAsStream("rulesets/rulesets.properties")); 30 String rulesetFilenames = props.getProperty("rulesets.filenames"); 31 List ruleSets = new ArrayList(); 32 for (StringTokenizer st = new StringTokenizer(rulesetFilenames, ","); st.hasMoreTokens();) { 33 ruleSets.add(createRuleSet(st.nextToken())); 34 } 35 return ruleSets.iterator(); 36 } catch (IOException ioe) { 37 throw new RuntimeException("Couldn't find rulesets.properties; please ensure that the rulesets directory is on the classpath. Here's the current classpath: " + System.getProperty("java.class.path")); 38 } 39 } 40 41 public RuleSet createRuleSet(String name, ClassLoader classLoader) throws RuleSetNotFoundException { 42 if (name.indexOf(',') == -1) { 43 return createRuleSet(tryToGetStreamTo(name, classLoader)); 44 } 45 46 RuleSet ruleSet = new RuleSet(); 47 for (StringTokenizer st = new StringTokenizer(name, ","); st.hasMoreTokens();) { 48 String ruleSetName = st.nextToken().trim(); 49 RuleSet tmpRuleSet = createRuleSet(ruleSetName, classLoader); 50 ruleSet.addRuleSet(tmpRuleSet); 51 } 52 return ruleSet; 53 } 54 55 /*** 56 * Creates a ruleset. If passed a comma-delimited string (rulesets/basic.xml,rulesets/unusedcode.xml) 57 * it will parse that string and create a new ruleset for each item in the list. 58 */ 59 public RuleSet createRuleSet(String name) throws RuleSetNotFoundException { 60 return createRuleSet(name, getClass().getClassLoader()); 61 } 62 63 public RuleSet createRuleSet(InputStream inputStream) { 64 return createRuleSet(inputStream, getClass().getClassLoader()); 65 } 66 67 public RuleSet createRuleSet(InputStream inputStream, ClassLoader classLoader) { 68 try { 69 DocumentBuilder builder = DocumentBuilderFactory.newInstance().newDocumentBuilder(); 70 Document doc = builder.parse(inputStream); 71 Element root = doc.getDocumentElement(); 72 73 RuleSet ruleSet = new RuleSet(); 74 ruleSet.setName(root.getAttribute("name")); 75 ruleSet.setDescription(root.getChildNodes().item(1).getFirstChild().getNodeValue()); 76 77 NodeList rules = root.getElementsByTagName("rule"); 78 for (int i = 0; i < rules.getLength(); i++) { 79 Node ruleNode = rules.item(i); 80 if (ruleNode.getAttributes().getNamedItem("ref") != null) { 81 parseExternallyDefinedRule(ruleSet, ruleNode); 82 } else { 83 parseInternallyDefinedRule(ruleSet, ruleNode, classLoader); 84 } 85 } 86 return ruleSet; 87 } catch (Exception e) { 88 e.printStackTrace(); 89 throw new RuntimeException("Couldn't read from that source: " + e.getMessage()); 90 } 91 } 92 93 private void parseInternallyDefinedRule(RuleSet ruleSet, Node ruleNode, ClassLoader classLoader) throws InstantiationException, IllegalAccessException, ClassNotFoundException { 94 Rule rule = (Rule) Class.forName(ruleNode.getAttributes().getNamedItem("class").getNodeValue(), true, classLoader).newInstance(); 95 rule.setName(ruleNode.getAttributes().getNamedItem("name").getNodeValue()); 96 rule.setMessage(ruleNode.getAttributes().getNamedItem("message").getNodeValue()); 97 // get the description, priority, example and properties (if any) 98 Node node = ruleNode.getFirstChild(); 99 while (node != null) { 100 if (node.getNodeName() != null && node.getNodeName().equals("description")) { 101 rule.setDescription(node.getFirstChild().getNodeValue()); 102 } 103 104 if (node.getNodeName() != null && node.getNodeName().equals("priority")) { 105 rule.setPriority(Integer.parseInt(node.getFirstChild().getNodeValue().trim())); 106 } 107 108 if (node.getNodeName() != null && node.getNodeName().equals("example")) { 109 rule.setExample(node.getFirstChild().getNextSibling().getNodeValue()); 110 } 111 112 parseProperties(node, rule); 113 114 node = node.getNextSibling(); 115 } 116 ruleSet.addRule(rule); 117 } 118 119 /*** 120 * Here's how to exclude rules: 121 * 122 * <rule ref="rulesets/braces.xml"> 123 * <exclude name="WhileLoopsMustUseBracesRule"/> 124 * <exclude name="IfElseStmtsMustUseBracesRule"/> 125 * </rule> 126 * 127 */ 128 private void parseExternallyDefinedRule(RuleSet ruleSet, Node ruleNode) throws RuleSetNotFoundException { 129 String referenceValue = ruleNode.getAttributes().getNamedItem("ref").getNodeValue(); 130 if (referenceValue.endsWith("xml")) { 131 parseWithExcludes(ruleNode, referenceValue, ruleSet); 132 } else { 133 parseSimpleReference(referenceValue, ruleSet); 134 } 135 } 136 137 private void parseSimpleReference(String referenceValue, RuleSet ruleSet) throws RuleSetNotFoundException { 138 RuleSetFactory rsf = new RuleSetFactory(); 139 ExternalRuleID externalRuleID = new ExternalRuleID(referenceValue); 140 RuleSet externalRuleSet = rsf.createRuleSet(ResourceLoader.loadResourceAsStream(externalRuleID.getFilename())); 141 ruleSet.addRule(externalRuleSet.getRuleByName(externalRuleID.getRuleName())); 142 } 143 144 private void parseWithExcludes(Node ruleNode, String referenceValue, RuleSet ruleSet) throws RuleSetNotFoundException { 145 NodeList excludeNodes = ruleNode.getChildNodes(); 146 Set excludes = new HashSet(); 147 for (int i=0; i<excludeNodes.getLength(); i++) { 148 Node node = excludeNodes.item(i); 149 if (node.getAttributes() != null) { 150 excludes.add(node.getAttributes().getNamedItem("name").getNodeValue()); 151 } 152 } 153 RuleSetFactory rsf = new RuleSetFactory(); 154 RuleSet externalRuleSet = rsf.createRuleSet(ResourceLoader.loadResourceAsStream(referenceValue)); 155 for (Iterator i = externalRuleSet.getRules().iterator(); i.hasNext();) { 156 Rule rule = (Rule)i.next(); 157 if (!excludes.contains(rule.getName())) { 158 ruleSet.addRule(rule); 159 } 160 } 161 } 162 163 private void parseProperties(Node node, Rule rule) { 164 if (node.getNodeName().equals("properties")) { 165 Node propNode = node.getFirstChild().getNextSibling(); 166 while (propNode != null && propNode.getAttributes() != null) { 167 propNode = parseProperty(propNode, rule); 168 } 169 } 170 } 171 172 private Node parseProperty(Node propNode, Rule rule) { 173 String propName = propNode.getAttributes().getNamedItem("name").getNodeValue(); 174 String propValue; 175 if (propName.equals("xpath")) { 176 Node xpathExprNode = propNode.getFirstChild().getNextSibling(); 177 propValue = xpathExprNode.getFirstChild().getNextSibling().getNodeValue(); 178 } else { 179 propValue = propNode.getAttributes().getNamedItem("value").getNodeValue(); 180 } 181 rule.addProperty(propName, propValue); 182 return propNode.getNextSibling().getNextSibling(); 183 } 184 185 private InputStream tryToGetStreamTo(String name, ClassLoader loader) throws RuleSetNotFoundException { 186 InputStream in = ResourceLoader.loadResourceAsStream(name, loader); 187 if (in == null) { 188 throw new RuleSetNotFoundException("Can't find resource " + name + ". Make sure the resource is a valid file or URL or is on the CLASSPATH"); 189 } 190 return in; 191 } 192 }

This page was automatically generated by Maven