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 }