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.ast.ASTCompilationUnit; 8 import net.sourceforge.pmd.ast.ASTVariableDeclaratorId; 9 import net.sourceforge.pmd.ast.SimpleNode; 10 import net.sourceforge.pmd.jaxen.DocumentNavigator; 11 import org.jaxen.BaseXPath; 12 import org.jaxen.JaxenException; 13 import org.jaxen.SimpleVariableContext; 14 import org.jaxen.XPath; 15 16 import java.io.PrintStream; 17 import java.io.PrintWriter; 18 import java.text.MessageFormat; 19 import java.util.Iterator; 20 import java.util.List; 21 import java.util.Map.Entry; 22 23 public class XPathRule extends AbstractRule { 24 25 private XPath xpath; 26 27 public Object visit(ASTCompilationUnit compilationUnit, Object data) { 28 try { 29 initializeXPathExpression(); 30 List results = xpath.selectNodes(compilationUnit); 31 for (Iterator i = results.iterator(); i.hasNext();) { 32 SimpleNode n = (SimpleNode) i.next(); 33 String msg = getMessage(); 34 if (n instanceof ASTVariableDeclaratorId && getBooleanProperty("pluginname")) { 35 msg = MessageFormat.format(msg, new Object[]{n.getImage()}); 36 } 37 addViolation(data, n, msg); 38 } 39 } catch (JaxenException ex) { 40 throwJaxenAsRuntime(ex); 41 } 42 return data; 43 } 44 45 private void initializeXPathExpression() throws JaxenException { 46 if (xpath != null) { 47 return; 48 } 49 xpath = new BaseXPath(getStringProperty("xpath"), new DocumentNavigator()); 50 if (properties.size() > 1) { 51 SimpleVariableContext vc = new SimpleVariableContext(); 52 for (Iterator i = properties.entrySet().iterator(); i.hasNext();) { 53 Entry e = (Entry) i.next(); 54 if (!"xpath".equals(e.getKey())) { 55 vc.setVariableValue((String)e.getKey(), e.getValue()); 56 } 57 } 58 xpath.setVariableContext(vc); 59 } 60 } 61 62 private static void throwJaxenAsRuntime(final JaxenException ex) { 63 throw new RuntimeException() { 64 public void printStackTrace() { 65 super.printStackTrace(); 66 ex.printStackTrace(); 67 } 68 public void printStackTrace(PrintWriter writer) { 69 super.printStackTrace(writer); 70 ex.printStackTrace(writer); 71 } 72 public void printStackTrace(PrintStream stream) { 73 super.printStackTrace(stream); 74 ex.printStackTrace(stream); 75 } 76 public String getMessage() { 77 return super.getMessage() + ex.getMessage(); 78 } 79 }; 80 } 81 }