Clover coverage report - PMD - 3.3
Coverage timestamp: Thu Sep 15 2005 17:59:57 EDT
file stats: LOC: 128   Methods: 4
NCLOC: 86   Classes: 1
 
 Source file Conditionals Statements Methods TOTAL
CloseConnection.java 60.7% 86% 100% 77.3%
coverage coverage
 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.AbstractRule;
 7    import net.sourceforge.pmd.ast.ASTBlock;
 8    import net.sourceforge.pmd.ast.ASTClassOrInterfaceType;
 9    import net.sourceforge.pmd.ast.ASTCompilationUnit;
 10    import net.sourceforge.pmd.ast.ASTImportDeclaration;
 11    import net.sourceforge.pmd.ast.ASTLocalVariableDeclaration;
 12    import net.sourceforge.pmd.ast.ASTMethodDeclaration;
 13    import net.sourceforge.pmd.ast.ASTName;
 14    import net.sourceforge.pmd.ast.ASTReferenceType;
 15    import net.sourceforge.pmd.ast.ASTTryStatement;
 16    import net.sourceforge.pmd.ast.ASTType;
 17    import net.sourceforge.pmd.ast.ASTVariableDeclaratorId;
 18    import net.sourceforge.pmd.ast.Node;
 19   
 20    import java.util.ArrayList;
 21    import java.util.Iterator;
 22    import java.util.List;
 23    import java.util.Vector;
 24   
 25   
 26    /**
 27    * Makes sure you close your database connections. It does this by
 28    * looking for code patterned like this:
 29    * <pre>
 30    * Connection c = X;
 31    * try {
 32    * // do stuff, and maybe catch something
 33    * } finally {
 34    * c.close();
 35    * }
 36    * </pre>
 37    */
 38    public class CloseConnection extends AbstractRule {
 39   
 40  3 public Object visit(ASTCompilationUnit node, Object data) {
 41  3 if (!importsJavaSqlPackage(node)) {
 42  2 return data;
 43    }
 44  1 return super.visit(node, data);
 45    }
 46   
 47  1 public Object visit(ASTMethodDeclaration node, Object data) {
 48  1 List vars = node.findChildrenOfType(ASTLocalVariableDeclaration.class);
 49  1 List ids = new Vector();
 50   
 51    // find all variable references to Connection objects
 52  1 for (Iterator it = vars.iterator(); it.hasNext();) {
 53  1 ASTLocalVariableDeclaration var = (ASTLocalVariableDeclaration) it.next();
 54  1 ASTType type = (ASTType) var.jjtGetChild(0);
 55   
 56  1 if (type.jjtGetChild(0) instanceof ASTReferenceType) {
 57  1 ASTReferenceType ref = (ASTReferenceType)type.jjtGetChild(0);
 58  1 if (ref.jjtGetChild(0) instanceof ASTClassOrInterfaceType) {
 59  1 ASTClassOrInterfaceType clazz = (ASTClassOrInterfaceType)ref.jjtGetChild(0);
 60  1 if (clazz.getImage().equals("Connection")) {
 61  1 ASTVariableDeclaratorId id = (ASTVariableDeclaratorId) var.jjtGetChild(1).jjtGetChild(0);
 62  1 ids.add(id);
 63    }
 64    }
 65    }
 66    }
 67   
 68    // if there are connections, ensure each is closed.
 69  1 for (int i = 0; i < ids.size(); i++) {
 70  1 ASTVariableDeclaratorId x = (ASTVariableDeclaratorId) ids.get(i);
 71  1 ensureClosed((ASTLocalVariableDeclaration) x.jjtGetParent()
 72    .jjtGetParent(), x, data);
 73    }
 74  1 return data;
 75    }
 76   
 77  1 private void ensureClosed(ASTLocalVariableDeclaration var,
 78    ASTVariableDeclaratorId id, Object data) {
 79    // What are the chances of a Connection being instantiated in a
 80    // for-loop init block? Anyway, I'm lazy!
 81  1 String target = id.getImage() + ".close";
 82  1 Node n = var;
 83   
 84  ? while (!((n = n.jjtGetParent()) instanceof ASTBlock));
 85   
 86  1 ASTBlock top = (ASTBlock) n;
 87   
 88  1 List tryblocks = new Vector();
 89  1 top.findChildrenOfType(ASTTryStatement.class, tryblocks, true);
 90   
 91  1 boolean closed = false;
 92   
 93    // look for try blocks below the line the variable was
 94    // introduced and make sure there is a .close call in a finally
 95    // block.
 96  1 for (Iterator it = tryblocks.iterator(); it.hasNext();) {
 97  1 ASTTryStatement t = (ASTTryStatement) it.next();
 98   
 99  1 if ((t.getBeginLine() > id.getBeginLine()) && (t.hasFinally())) {
 100  0 ASTBlock f = (ASTBlock)t.getFinally().jjtGetChild(0);
 101  0 List names = new ArrayList();
 102  0 f.findChildrenOfType(ASTName.class, names, true);
 103  0 for (Iterator it2 = names.iterator(); it2.hasNext();) {
 104  0 if (((ASTName) it2.next()).getImage().equals(target)) {
 105  0 closed = true;
 106    }
 107    }
 108    }
 109    }
 110   
 111    // if all is not well, complain
 112  1 if (!closed) {
 113  1 addViolation(data, id);
 114    }
 115    }
 116   
 117  3 private boolean importsJavaSqlPackage(ASTCompilationUnit node) {
 118  3 List nodes = node.findChildrenOfType(ASTImportDeclaration.class);
 119  3 for (Iterator i = nodes.iterator(); i.hasNext();) {
 120  2 ASTImportDeclaration n = (ASTImportDeclaration)i.next();
 121  2 if (n.getPackageName().startsWith("java.sql")) {
 122  1 return true;
 123    }
 124    }
 125  2 return false;
 126    }
 127   
 128    }