KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > net > sourceforge > pmd > rules > XPathRule


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.CommonAbstractRule;
7 import net.sourceforge.pmd.RuleContext;
8 import net.sourceforge.pmd.ast.ASTVariableDeclaratorId;
9 import net.sourceforge.pmd.ast.Node;
10 import net.sourceforge.pmd.ast.SimpleNode;
11 import net.sourceforge.pmd.jaxen.DocumentNavigator;
12 import net.sourceforge.pmd.jaxen.MatchesFunction;
13
14 import org.jaxen.BaseXPath;
15 import org.jaxen.JaxenException;
16 import org.jaxen.SimpleVariableContext;
17 import org.jaxen.XPath;
18
19 import java.io.PrintStream JavaDoc;
20 import java.io.PrintWriter JavaDoc;
21 import java.util.Iterator JavaDoc;
22 import java.util.List JavaDoc;
23 import java.util.Map.Entry;
24
25 /**
26  * Rule that tries to match an XPath expression against a DOM
27  * view of the AST of a "compilation unit".
28  * <p/>
29  * This rule needs a property "xpath".
30  */

31 public class XPathRule extends CommonAbstractRule {
32
33     public static Class JavaDoc loadClass(ClassLoader JavaDoc classloader, String JavaDoc xpath, String JavaDoc name) {
34         if (xpath.indexOf('|') != -1) {
35             //System.err.println(name + " not a dynamic rule: " + xpath.trim().replaceAll("\n", ""));
36
return XPathRule.class;
37         }
38         String JavaDoc part = xpath.trim();
39         
40         // Need to use DOTALL mode because of potential line terminators
41
if (!part.matches("(?s)//\\w+\\W.*")) {
42             //System.err.println(name + " not a dynamic rule: " + xpath.trim().replaceAll("\n", ""));
43
return XPathRule.class;
44         }
45         
46         String JavaDoc tail = part.replaceFirst("^//\\w+", "");
47         String JavaDoc nodeName = part.substring(2, part.indexOf(tail));
48
49         return DynamicXPathRule.loadClass(classloader, nodeName);
50     }
51
52     private XPath xpath;
53     private boolean regexpFunctionRegistered;
54
55     /**
56      * Evaluate the AST with compilationUnit as root-node, against
57      * the XPath expression found as property with name "xpath".
58      * All matches are reported as violations.
59      *
60      * @param compilationUnit the Node that is the root of the AST to be checked
61      * @param data
62      */

63     public void evaluate(Node compilationUnit, RuleContext data) {
64         try {
65             initializeXPathExpression();
66             List JavaDoc results = xpath.selectNodes(compilationUnit);
67             for (Iterator JavaDoc i = results.iterator(); i.hasNext();) {
68                 SimpleNode n = (SimpleNode) i.next();
69                 if (n instanceof ASTVariableDeclaratorId && getBooleanProperty("pluginname")) {
70                     addViolation(data, n, n.getImage());
71                 } else {
72                     addViolation(data, (SimpleNode) n, getMessage());
73                 }
74             }
75         } catch (JaxenException ex) {
76             throwJaxenAsRuntime(ex);
77         }
78     }
79
80     private void initializeXPathExpression() throws JaxenException {
81         if (xpath != null) {
82             return;
83         }
84
85         if (!regexpFunctionRegistered) {
86             MatchesFunction.registerSelfInSimpleContext();
87             regexpFunctionRegistered = true;
88         }
89
90         xpath = new BaseXPath(getStringProperty("xpath"), new DocumentNavigator());
91         if (properties.size() > 1) {
92             SimpleVariableContext vc = new SimpleVariableContext();
93             for (Iterator JavaDoc i = properties.entrySet().iterator(); i.hasNext();) {
94                 Entry e = (Entry) i.next();
95                 if (!"xpath".equals(e.getKey())) {
96                     vc.setVariableValue((String JavaDoc) e.getKey(), e.getValue());
97                 }
98             }
99             xpath.setVariableContext(vc);
100         }
101     }
102
103     private static void throwJaxenAsRuntime(final JaxenException ex) {
104         throw new RuntimeException JavaDoc() {
105             public void printStackTrace() {
106                 super.printStackTrace();
107                 ex.printStackTrace();
108             }
109
110             public void printStackTrace(PrintWriter JavaDoc writer) {
111                 super.printStackTrace(writer);
112                 ex.printStackTrace(writer);
113             }
114
115             public void printStackTrace(PrintStream JavaDoc stream) {
116                 super.printStackTrace(stream);
117                 ex.printStackTrace(stream);
118             }
119
120             public String JavaDoc getMessage() {
121                 return super.getMessage() + ex.getMessage();
122             }
123         };
124     }
125
126     /**
127      * Apply the rule to all compilation units.
128      */

129     public void apply(List JavaDoc astCompilationUnits, RuleContext ctx) {
130         for (Iterator JavaDoc i = astCompilationUnits.iterator(); i.hasNext();) {
131             evaluate((Node) i.next(), ctx);
132         }
133     }
134 }
135
Popular Tags