/** * BSD-style license; for more info see http://pmd.sourceforge.net/license.html */ package net.sourceforge.pmd.lang.java.rule.basic; import java.util.HashMap; import java.util.HashSet; import java.util.Map; import java.util.Set; import net.sourceforge.pmd.lang.ast.Node; import net.sourceforge.pmd.lang.java.ast.ASTClassOrInterfaceType; import net.sourceforge.pmd.lang.java.ast.ASTIfStatement; import net.sourceforge.pmd.lang.java.ast.ASTLocalVariableDeclaration; import net.sourceforge.pmd.lang.java.ast.ASTMethodDeclaration; import net.sourceforge.pmd.lang.java.ast.ASTName; import net.sourceforge.pmd.lang.java.ast.ASTReturnStatement; import net.sourceforge.pmd.lang.java.ast.ASTType; import net.sourceforge.pmd.lang.java.ast.ASTVariableDeclarator; import net.sourceforge.pmd.lang.java.ast.ASTVariableDeclaratorId; import net.sourceforge.pmd.lang.java.ast.ASTWhileStatement; import net.sourceforge.pmd.lang.java.rule.AbstractJavaRule; /** * Rule that verifies, that the return values of next(), first(), last(), etc. * calls to a java.sql.ResultSet are actually verified. * */ public class CheckResultSetRule extends AbstractJavaRule { private Map<String, Node> resultSetVariables = new HashMap<>(); private static Set<String> methods = new HashSet<>(); static { methods.add(".next"); methods.add(".previous"); methods.add(".last"); methods.add(".first"); } @Override public Object visit(ASTMethodDeclaration node, Object data) { resultSetVariables.clear(); return super.visit(node, data); } @Override public Object visit(ASTLocalVariableDeclaration node, Object data) { ASTClassOrInterfaceType type = node.getFirstChildOfType(ASTType.class) .getFirstDescendantOfType(ASTClassOrInterfaceType.class); if (type != null && (type.getType() != null && "java.sql.ResultSet".equals(type.getType().getName()) || "ResultSet".equals(type.getImage()))) { ASTVariableDeclarator declarator = node.getFirstChildOfType(ASTVariableDeclarator.class); if (declarator != null) { ASTName name = declarator.getFirstDescendantOfType(ASTName.class); if (type.getType() != null || name != null && name.getImage().endsWith("executeQuery")) { ASTVariableDeclaratorId id = declarator.getFirstChildOfType(ASTVariableDeclaratorId.class); resultSetVariables.put(id.getImage(), node); } } } return super.visit(node, data); } @Override public Object visit(ASTName node, Object data) { String image = node.getImage(); String var = getResultSetVariableName(image); if (var != null && resultSetVariables.containsKey(var) && node.getFirstParentOfType(ASTIfStatement.class) == null && node.getFirstParentOfType(ASTWhileStatement.class) == null && node.getFirstParentOfType(ASTReturnStatement.class) == null) { addViolation(data, resultSetVariables.get(var)); } return super.visit(node, data); } private String getResultSetVariableName(String image) { if (image.contains(".")) { for (String method : methods) { if (image.endsWith(method)) { return image.substring(0, image.lastIndexOf(method)); } } } return null; } }