1 /*** 2 * BSD-style license; for more info see http://pmd.sourceforge.net/license.html 3 */ 4 package net.sourceforge.pmd.rules; 5 6 import net.sourceforge.pmd.AbstractRule; 7 import net.sourceforge.pmd.RuleContext; 8 import net.sourceforge.pmd.ast.ASTCompilationUnit; 9 import net.sourceforge.pmd.ast.ASTVariableDeclaratorId; 10 import net.sourceforge.pmd.ast.SimpleNode; 11 import net.sourceforge.pmd.ast.ASTPackageDeclaration; 12 import net.sourceforge.pmd.ast.Node; 13 import net.sourceforge.pmd.jaxen.DocumentNavigator; 14 import org.jaxen.BaseXPath; 15 import org.jaxen.JaxenException; 16 import org.jaxen.XPath; 17 18 import java.io.PrintStream; 19 import java.io.PrintWriter; 20 import java.text.MessageFormat; 21 import java.util.Iterator; 22 23 public class XPathRule extends AbstractRule { 24 25 private XPath xpath; 26 27 public Object visit(ASTCompilationUnit node, Object data) { 28 try { 29 findPackageName(node); 30 init(); 31 for (Iterator iter = xpath.selectNodes(node).iterator(); iter.hasNext();) { 32 SimpleNode actualNode = (SimpleNode) iter.next(); 33 RuleContext ctx = (RuleContext) data; 34 String msg = getMessage(); 35 if (actualNode instanceof ASTVariableDeclaratorId && getBooleanProperty("pluginname")) { 36 msg = MessageFormat.format(msg, new Object[]{actualNode.getImage()}); 37 } 38 ctx.getReport().addRuleViolation(createRuleViolation(ctx, actualNode, msg)); 39 } 40 } catch (JaxenException ex) { 41 throwJaxenAsRuntime(ex); 42 } 43 return data; 44 } 45 46 private void findPackageName(ASTCompilationUnit node) { 47 for (int i=0; i<node.jjtGetNumChildren(); i++) { 48 Node n = node.jjtGetChild(i); 49 if (n instanceof ASTPackageDeclaration) { 50 String name = ((SimpleNode)n.jjtGetChild(0)).getImage(); 51 setPackageName(name); 52 break; 53 } 54 } 55 } 56 57 private void init() throws JaxenException { 58 if (xpath == null) { 59 String path = getStringProperty("xpath"); 60 String subst = getStringProperty("subst"); 61 if (subst != null && subst.length() > 0) { 62 path = MessageFormat.format(path, new String[]{subst}); 63 } 64 xpath = new BaseXPath(path, new DocumentNavigator()); 65 } 66 } 67 68 private static void throwJaxenAsRuntime(final JaxenException ex) { 69 throw new RuntimeException() { 70 public void printStackTrace() { 71 super.printStackTrace(); 72 ex.printStackTrace(); 73 } 74 75 public void printStackTrace(PrintWriter writer) { 76 super.printStackTrace(writer); 77 ex.printStackTrace(writer); 78 } 79 80 public void printStackTrace(PrintStream stream) { 81 super.printStackTrace(stream); 82 ex.printStackTrace(stream); 83 } 84 85 public String getMessage() { 86 return super.getMessage() + ex.getMessage(); 87 } 88 }; 89 } 90 }