View Javadoc
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.RuleContext; 8 import net.sourceforge.pmd.ast.ASTBlock; 9 import net.sourceforge.pmd.ast.ASTLocalVariableDeclaration; 10 import net.sourceforge.pmd.ast.ASTMethodDeclaration; 11 import net.sourceforge.pmd.ast.ASTName; 12 import net.sourceforge.pmd.ast.ASTTryStatement; 13 import net.sourceforge.pmd.ast.ASTType; 14 import net.sourceforge.pmd.ast.ASTVariableDeclaratorId; 15 import net.sourceforge.pmd.ast.Node; 16 17 import java.util.ArrayList; 18 import java.util.Iterator; 19 import java.util.List; 20 import java.util.Vector; 21 22 23 /*** 24 * Makes sure you close your database connections. It does this by 25 * looking for code patterned like this: 26 * <pre> 27 * Connection c = X; 28 * try { 29 * // do stuff, and maybe catch something 30 * } finally { 31 * c.close(); 32 * } 33 * </pre> 34 */ 35 public class CloseConnectionRule extends AbstractRule { 36 public Object visit(ASTMethodDeclaration node, Object data) { 37 List vars = node.findChildrenOfType(ASTLocalVariableDeclaration.class); 38 List ids = new Vector(); 39 40 // find all variable references to Connection objects 41 for (Iterator it = vars.iterator(); it.hasNext();) { 42 ASTLocalVariableDeclaration var = (ASTLocalVariableDeclaration) it.next(); 43 ASTType type = (ASTType) var.jjtGetChild(0); 44 45 if (type.jjtGetChild(0) instanceof ASTName && ((ASTName) type.jjtGetChild(0)).getImage().equals("Connection")) { 46 ASTVariableDeclaratorId id = (ASTVariableDeclaratorId) var.jjtGetChild(1).jjtGetChild(0); 47 ids.add(id); 48 } 49 } 50 51 // if there are connections, ensure each is closed. 52 for (int i = 0; i < ids.size(); i++) { 53 ASTVariableDeclaratorId x = (ASTVariableDeclaratorId) ids.get(i); 54 ensureClosed((ASTLocalVariableDeclaration) x.jjtGetParent() 55 .jjtGetParent(), x, data); 56 } 57 return data; 58 } 59 60 private void ensureClosed(ASTLocalVariableDeclaration var, 61 ASTVariableDeclaratorId id, Object data) { 62 // What are the chances of a Connection being instantiated in a 63 // for-loop init block? Anyway, I'm lazy! 64 String target = id.getImage() + ".close"; 65 Node n = var; 66 67 while (!((n = n.jjtGetParent()) instanceof ASTBlock)) 68 ; 69 70 ASTBlock top = (ASTBlock) n; 71 72 List tryblocks = new Vector(); 73 top.findChildrenOfType(ASTTryStatement.class, tryblocks, true); 74 75 boolean closed = false; 76 77 // look for try blocks below the line the variable was 78 // introduced and make sure there is a .close call in a finally 79 // block. 80 for (Iterator it = tryblocks.iterator(); it.hasNext();) { 81 ASTTryStatement t = (ASTTryStatement) it.next(); 82 83 if ((t.getBeginLine() > id.getBeginLine()) && (t.hasFinally())) { 84 ASTBlock f = t.getFinallyBlock(); 85 List names = new ArrayList(); 86 f.findChildrenOfType(ASTName.class, names, true); 87 for (Iterator it2 = names.iterator(); it2.hasNext();) { 88 if (((ASTName) it2.next()).getImage().equals(target)) { 89 closed = true; 90 } 91 } 92 } 93 } 94 95 // if all is not well, complain 96 if (!closed) { 97 RuleContext ctx = (RuleContext) data; 98 ctx.getReport().addRuleViolation(createRuleViolation(ctx, id.getBeginLine(), getMessage())); 99 } 100 } 101 }

This page was automatically generated by Maven