Clover coverage report - PMD - 3.9 Coverage timestamp: Tue Dec 19 2006 09:38:44 EST FRAMES NO FRAMES |
file stats: | LOC: | 134 |  | Methods: | 9
| NCLOC: | 93 |  | Classes: | 1
Source file | Conditionals | Statements | Methods | TOTAL
XPathRule.java | 90% | 75% | 44.4% | 75.4% |

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;
20 |  | import java.io.PrintWriter;
21 |  | import java.util.Iterator;
22 |  | import java.util.List;
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 | 2451 | public static Class loadClass(ClassLoader classloader, String xpath, String name) {
34 | 2451 | if (xpath.indexOf('|') != -1) {
35 |  | //System.err.println(name + " not a dynamic rule: " + xpath.trim().replaceAll("\n", ""));
36 | 70 | return XPathRule.class;
37 |  | }
38 | 2381 | String part = xpath.trim();
39 |  |
40 |  | // Need to use DOTALL mode because of potential line terminators
41 | 2381 | if (!part.matches("(?s)//\\w+\\W.*")) {
42 |  | //System.err.println(name + " not a dynamic rule: " + xpath.trim().replaceAll("\n", ""));
43 | 0 | return XPathRule.class;
44 |  | }
45 |  |
46 | 2381 | String tail = part.replaceFirst("^//\\w+", "");
47 | 2381 | String nodeName = part.substring(2, part.indexOf(tail));
48 |  |
49 | 2381 | 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 | 26 | public void evaluate(Node compilationUnit, RuleContext data) {
64 | 26 | try {
65 | 26 | initializeXPathExpression();
66 | 26 | List results = xpath.selectNodes(compilationUnit);
67 | 26 | for (Iterator i = results.iterator(); i.hasNext();) {
68 | 18 | SimpleNode n = (SimpleNode) i.next();
69 | 18 | if (n instanceof ASTVariableDeclaratorId && getBooleanProperty("pluginname")) {
70 | 1 | addViolation(data, n, n.getImage());
71 |  | } else {
72 | 17 | addViolation(data, (SimpleNode) n, getMessage());
73 |  | }
74 |  | }
75 |  | } catch (JaxenException ex) {
76 | 0 | throwJaxenAsRuntime(ex);
77 |  | }
78 |  | }
79 |  |
80 | 26 | private void initializeXPathExpression() throws JaxenException {
81 | 26 | if (xpath != null) {
82 | 13 | return;
83 |  | }
84 |  |
85 | 13 | if (!regexpFunctionRegistered) {
86 | 13 | MatchesFunction.registerSelfInSimpleContext();
87 | 13 | regexpFunctionRegistered = true;
88 |  | }
89 |  |
90 | 13 | xpath = new BaseXPath(getStringProperty("xpath"), new DocumentNavigator());
91 | 13 | if (properties.size() > 1) {
92 | 2 | SimpleVariableContext vc = new SimpleVariableContext();
93 | 2 | for (Iterator i = properties.entrySet().iterator(); i.hasNext();) {
94 | 4 | Entry e = (Entry) i.next();
95 | 4 | if (!"xpath".equals(e.getKey())) {
96 | 2 | vc.setVariableValue((String) e.getKey(), e.getValue());
97 |  | }
98 |  | }
99 | 2 | xpath.setVariableContext(vc);
100 |  | }
101 |  | }
102 |  |
103 | 0 | private static void throwJaxenAsRuntime(final JaxenException ex) {
104 | 0 | throw new RuntimeException() {
105 | 0 | public void printStackTrace() {
106 | 0 | super.printStackTrace();
107 | 0 | ex.printStackTrace();
108 |  | }
109 |  |
110 | 0 | public void printStackTrace(PrintWriter writer) {
111 | 0 | super.printStackTrace(writer);
112 | 0 | ex.printStackTrace(writer);
113 |  | }
114 |  |
115 | 0 | public void printStackTrace(PrintStream stream) {
116 | 0 | super.printStackTrace(stream);
117 | 0 | ex.printStackTrace(stream);
118 |  | }
119 |  |
120 | 0 | public String getMessage() {
121 | 0 | return super.getMessage() + ex.getMessage();
122 |  | }
123 |  | };
124 |  | }
125 |  |
126 |  | /**
127 |  | * Apply the rule to all compilation units.
128 |  | */
129 | 26 | public void apply(List astCompilationUnits, RuleContext ctx) {
130 | 26 | for (Iterator i = astCompilationUnits.iterator(); i.hasNext();) {
131 | 26 | evaluate((Node) i.next(), ctx);
132 |  | }
133 |  | }
134 |  | }