1 package net.sourceforge.pmd.rules; 2 3 import java.util.HashMap ; 4 import java.util.Iterator ; 5 import java.util.List ; 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 classes = new HashMap (); 29 30 public static synchronized Class loadClass(ClassLoader classloader, String type) { 31 Class c = (Class ) 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 { 43 ByteArrayClassLoader(ClassLoader parent) { 44 super(parent); 45 } 46 47 Class loadClass(byte[] data) { 48 return defineClass(null, data, 0, data.length, null); 49 } 50 } 51 52 private static byte[] buildClass(String type) { 53 String className = "net/sourceforge/pmd/rules/" + type + "XPathRule"; 54 String 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 101 public void evaluate(Node compilationUnit, Object data) { 102 try { 103 initializeXPathExpression(); 104 List results = xpath.selectNodes(compilationUnit); 105 for (Iterator 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 (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 prop = getStringProperty("xpath"); 129 130 String tail = prop.trim().replaceFirst("^//\\w+", ""); 131 String subquery = '.' + tail.trim(); 132 133 xpath = new BaseXPath(subquery, new DocumentNavigator()); 134 if (properties.size() > 1) { 135 SimpleVariableContext vc = new SimpleVariableContext(); 136 for (Iterator i = properties.entrySet().iterator(); i.hasNext();) { 137 Entry e = (Entry) i.next(); 138 if (!"xpath".equals(e.getKey())) { 139 vc.setVariableValue((String ) e.getKey(), e.getValue()); 140 } 141 } 142 xpath.setVariableContext(vc); 143 } 144 } 145 146 } 147 148 | Popular Tags |