Clover coverage report - PMD - 3.9
Coverage timestamp: Tue Dec 19 2006 09:38:44 EST
file stats: LOC: 147   Methods: 7
NCLOC: 110   Classes: 2
 
 Source file Conditionals Statements Methods TOTAL
DynamicXPathRule.java 93.8% 98.3% 100% 97.6%
coverage coverage
 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  2381 protected DynamicXPathRule() {
 26    }
 27   
 28    private static HashMap classes = new HashMap();
 29   
 30  2381 public static synchronized Class loadClass(ClassLoader classloader, String type) {
 31  2381 Class c = (Class) classes.get(type);
 32  2381 if (c == null) {
 33  1317 byte bytecode[] = buildClass(type);
 34  1317 c = new ByteArrayClassLoader(classloader).loadClass(bytecode);
 35   
 36  1317 classes.put(type, c);
 37    }
 38   
 39  2381 return c;
 40    }
 41   
 42    private static class ByteArrayClassLoader extends ClassLoader {
 43  1317 ByteArrayClassLoader(ClassLoader parent) {
 44  1317 super(parent);
 45    }
 46   
 47  1317 Class loadClass(byte[] data) {
 48  1317 return defineClass(null, data, 0, data.length, null);
 49    }
 50    }
 51   
 52  1317 private static byte[] buildClass(String type) {
 53  1317 String className = "net/sourceforge/pmd/rules/" + type + "XPathRule";
 54  1317 String methodSig = "(Lnet/sourceforge/pmd/ast/AST" + type + ";Ljava/lang/Object;)Ljava/lang/Object;";
 55   
 56  1317 ClassWriter cw = new ClassWriter(0);
 57  1317 MethodVisitor mv;
 58   
 59  1317 cw.visit(V1_4, ACC_PUBLIC + ACC_SUPER, className, null, "net/sourceforge/pmd/rules/DynamicXPathRule", null);
 60   
 61  1317 mv = cw.visitMethod(ACC_PUBLIC, "<init>", "()V", null, null);
 62  1317 mv.visitCode();
 63  1317 mv.visitVarInsn(ALOAD, 0);
 64  1317 mv.visitMethodInsn(INVOKESPECIAL, "net/sourceforge/pmd/rules/DynamicXPathRule", "<init>", "()V");
 65  1317 mv.visitInsn(RETURN);
 66  1317 mv.visitMaxs(1, 1);
 67  1317 mv.visitEnd();
 68   
 69  1317 mv = cw.visitMethod(ACC_PUBLIC, "visit", methodSig, null, null);
 70  1317 mv.visitCode();
 71  1317 mv.visitVarInsn(ALOAD, 0);
 72  1317 mv.visitVarInsn(ALOAD, 1);
 73  1317 mv.visitVarInsn(ALOAD, 2);
 74  1317 mv.visitMethodInsn(INVOKEVIRTUAL, className, "evaluate", "(Lnet/sourceforge/pmd/ast/Node;Ljava/lang/Object;)V");
 75  1317 mv.visitVarInsn(ALOAD, 0);
 76  1317 mv.visitVarInsn(ALOAD, 1);
 77  1317 mv.visitVarInsn(ALOAD, 2);
 78  1317 mv.visitMethodInsn(INVOKESPECIAL, "net/sourceforge/pmd/rules/DynamicXPathRule", "visit", methodSig);
 79  1317 mv.visitInsn(ARETURN);
 80  1317 mv.visitMaxs(3, 3);
 81  1317 mv.visitEnd();
 82   
 83  1317 cw.visitEnd();
 84   
 85  1317 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  572 public void evaluate(Node compilationUnit, Object data) {
 102  572 try {
 103  572 initializeXPathExpression();
 104  572 List results = xpath.selectNodes(compilationUnit);
 105  572 for (Iterator i = results.iterator(); i.hasNext();) {
 106  209 SimpleNode n = (SimpleNode) i.next();
 107  209 if (n instanceof ASTVariableDeclaratorId && getBooleanProperty("pluginname")) {
 108  11 addViolation(data, n, n.getImage());
 109    } else {
 110  198 addViolation(data, (SimpleNode) n, getMessage());
 111    }
 112    }
 113    } catch (JaxenException ex) {
 114  0 throw new RuntimeException(ex);
 115    }
 116    }
 117   
 118  572 private void initializeXPathExpression() throws JaxenException {
 119  572 if (xpath != null) {
 120  468 return;
 121    }
 122   
 123  104 if (!regexpFunctionRegistered) {
 124  104 MatchesFunction.registerSelfInSimpleContext();
 125  104 regexpFunctionRegistered = true;
 126    }
 127   
 128  104 String prop = getStringProperty("xpath");
 129   
 130  104 String tail = prop.trim().replaceFirst("^//\\w+", "");
 131  104 String subquery = '.' + tail.trim();
 132   
 133  104 xpath = new BaseXPath(subquery, new DocumentNavigator());
 134  104 if (properties.size() > 1) {
 135  13 SimpleVariableContext vc = new SimpleVariableContext();
 136  13 for (Iterator i = properties.entrySet().iterator(); i.hasNext();) {
 137  28 Entry e = (Entry) i.next();
 138  28 if (!"xpath".equals(e.getKey())) {
 139  15 vc.setVariableValue((String) e.getKey(), e.getValue());
 140    }
 141    }
 142  13 xpath.setVariableContext(vc);
 143    }
 144    }
 145   
 146    }
 147