KickJava   Java API By Example, From Geeks To Geeks.

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


1 package net.sourceforge.pmd.rules;
2
3 import java.util.HashMap JavaDoc;
4 import java.util.Iterator JavaDoc;
5 import java.util.List JavaDoc;
6 import java.util.Map.Entry;
7
8 import net.sourceforge.pmd.AbstractRule;
9 import net.sourceforge.pmd.ast.ASTVariableDeclaratorId;
10 import net.sourceforge.pmd.ast.Node;
11 import net.sourceforge.pmd.ast.SimpleNode;
12 import net.sourceforge.pmd.jaxen.DocumentNavigator;
13 import net.sourceforge.pmd.jaxen.MatchesFunction;
14
15 import org.jaxen.BaseXPath;
16 import org.jaxen.JaxenException;
17 import org.jaxen.SimpleVariableContext;
18 import org.jaxen.XPath;
19 import org.objectweb.asm.ClassWriter;
20 import org.objectweb.asm.MethodVisitor;
21 import org.objectweb.asm.Opcodes;
22
23 public class DynamicXPathRule extends AbstractRule implements Opcodes {
24
25     protected DynamicXPathRule() {
26     }
27
28     private static HashMap JavaDoc classes = new HashMap JavaDoc();
29
30     public static synchronized Class JavaDoc loadClass(ClassLoader JavaDoc classloader, String JavaDoc type) {
31         Class JavaDoc c = (Class JavaDoc) classes.get(type);
32         if (c == null) {
33             byte bytecode[] = buildClass(type);
34             c = new ByteArrayClassLoader(classloader).loadClass(bytecode);
35
36             classes.put(type, c);
37         }
38
39         return c;
40     }
41
42     private static class ByteArrayClassLoader extends ClassLoader JavaDoc {
43         ByteArrayClassLoader(ClassLoader JavaDoc parent) {
44             super(parent);
45         }
46         
47         Class JavaDoc loadClass(byte[] data) {
48             return defineClass(null, data, 0, data.length, null);
49         }
50     }
51
52     private static byte[] buildClass(String JavaDoc type) {
53         String JavaDoc className = "net/sourceforge/pmd/rules/" + type + "XPathRule";
54         String JavaDoc methodSig = "(Lnet/sourceforge/pmd/ast/AST" + type + ";Ljava/lang/Object;)Ljava/lang/Object;";
55
56         ClassWriter cw = new ClassWriter(0);
57         MethodVisitor mv;
58
59         cw.visit(V1_4, ACC_PUBLIC + ACC_SUPER, className, null, "net/sourceforge/pmd/rules/DynamicXPathRule", null);
60
61         mv = cw.visitMethod(ACC_PUBLIC, "<init>", "()V", null, null);
62         mv.visitCode();
63         mv.visitVarInsn(ALOAD, 0);
64         mv.visitMethodInsn(INVOKESPECIAL, "net/sourceforge/pmd/rules/DynamicXPathRule", "<init>", "()V");
65         mv.visitInsn(RETURN);
66         mv.visitMaxs(1, 1);
67         mv.visitEnd();
68
69         mv = cw.visitMethod(ACC_PUBLIC, "visit", methodSig, null, null);
70         mv.visitCode();
71         mv.visitVarInsn(ALOAD, 0);
72         mv.visitVarInsn(ALOAD, 1);
73         mv.visitVarInsn(ALOAD, 2);
74         mv.visitMethodInsn(INVOKEVIRTUAL, className, "evaluate", "(Lnet/sourceforge/pmd/ast/Node;Ljava/lang/Object;)V");
75         mv.visitVarInsn(ALOAD, 0);
76         mv.visitVarInsn(ALOAD, 1);
77         mv.visitVarInsn(ALOAD, 2);
78         mv.visitMethodInsn(INVOKESPECIAL, "net/sourceforge/pmd/rules/DynamicXPathRule", "visit", methodSig);
79         mv.visitInsn(ARETURN);
80         mv.visitMaxs(3, 3);
81         mv.visitEnd();
82
83         cw.visitEnd();
84
85         return cw.toByteArray();
86     }
87
88
89     private XPath xpath;
90
91     private boolean regexpFunctionRegistered;
92
93     /**
94      * Evaluate the AST with compilationUnit as root-node, against
95      * the XPath expression found as property with name "xpath".
96      * All matches are reported as violations.
97      *
98      * @param compilationUnit the Node that is the root of the AST to be checked
99      * @param data
100      */

101     public void evaluate(Node compilationUnit, Object JavaDoc data) {
102         try {
103             initializeXPathExpression();
104             List JavaDoc results = xpath.selectNodes(compilationUnit);
105             for (Iterator JavaDoc i = results.iterator(); i.hasNext();) {
106                 SimpleNode n = (SimpleNode) i.next();
107                 if (n instanceof ASTVariableDeclaratorId && getBooleanProperty("pluginname")) {
108                     addViolation(data, n, n.getImage());
109                 } else {
110                     addViolation(data, (SimpleNode) n, getMessage());
111                 }
112             }
113         } catch (JaxenException ex) {
114             throw new RuntimeException JavaDoc(ex);
115         }
116     }
117
118     private void initializeXPathExpression() throws JaxenException {
119         if (xpath != null) {
120             return;
121         }
122
123         if (!regexpFunctionRegistered) {
124             MatchesFunction.registerSelfInSimpleContext();
125             regexpFunctionRegistered = true;
126         }
127
128         String JavaDoc prop = getStringProperty("xpath");
129
130         String JavaDoc tail = prop.trim().replaceFirst("^//\\w+", "");
131         String JavaDoc subquery = '.' + tail.trim();
132         
133         xpath = new BaseXPath(subquery, new DocumentNavigator());
134         if (properties.size() > 1) {
135             SimpleVariableContext vc = new SimpleVariableContext();
136             for (Iterator JavaDoc i = properties.entrySet().iterator(); i.hasNext();) {
137                 Entry e = (Entry) i.next();
138                 if (!"xpath".equals(e.getKey())) {
139                     vc.setVariableValue((String JavaDoc) e.getKey(), e.getValue());
140                 }
141             }
142             xpath.setVariableContext(vc);
143         }
144     }
145
146 }
147
148
Popular Tags