View Javadoc
1   /**
2    * BSD-style license; for more info see http://pmd.sourceforge.net/license.html
3    */
4   package net.sourceforge.pmd.lang.java.rule.basic;
5   
6   import java.util.HashMap;
7   import java.util.HashSet;
8   import java.util.Map;
9   import java.util.Set;
10  
11  import net.sourceforge.pmd.lang.ast.Node;
12  import net.sourceforge.pmd.lang.java.ast.ASTClassOrInterfaceType;
13  import net.sourceforge.pmd.lang.java.ast.ASTIfStatement;
14  import net.sourceforge.pmd.lang.java.ast.ASTLocalVariableDeclaration;
15  import net.sourceforge.pmd.lang.java.ast.ASTMethodDeclaration;
16  import net.sourceforge.pmd.lang.java.ast.ASTName;
17  import net.sourceforge.pmd.lang.java.ast.ASTReturnStatement;
18  import net.sourceforge.pmd.lang.java.ast.ASTType;
19  import net.sourceforge.pmd.lang.java.ast.ASTVariableDeclarator;
20  import net.sourceforge.pmd.lang.java.ast.ASTVariableDeclaratorId;
21  import net.sourceforge.pmd.lang.java.ast.ASTWhileStatement;
22  import net.sourceforge.pmd.lang.java.rule.AbstractJavaRule;
23  
24  /**
25   * Rule that verifies, that the return values of next(), first(), last(), etc.
26   * calls to a java.sql.ResultSet are actually verified.
27   *
28   */
29  public class CheckResultSetRule extends AbstractJavaRule {
30  
31      private Map<String, Node> resultSetVariables = new HashMap<>();
32  
33      private static Set<String> methods = new HashSet<>();
34      static {
35          methods.add(".next");
36          methods.add(".previous");
37          methods.add(".last");
38          methods.add(".first");
39      }
40  
41      @Override
42      public Object visit(ASTMethodDeclaration node, Object data) {
43          resultSetVariables.clear();
44          return super.visit(node, data);
45      }
46  
47      @Override
48      public Object visit(ASTLocalVariableDeclaration node, Object data) {
49          ASTClassOrInterfaceType type = node.getFirstChildOfType(ASTType.class).getFirstDescendantOfType(
50                  ASTClassOrInterfaceType.class);
51          if (type != null
52                  && (type.getType() != null && "java.sql.ResultSet".equals(type.getType().getName()) || "ResultSet"
53                          .equals(type.getImage()))) {
54              ASTVariableDeclarator declarator = node.getFirstChildOfType(ASTVariableDeclarator.class);
55              if (declarator != null) {
56                  ASTName name = declarator.getFirstDescendantOfType(ASTName.class);
57                  if (type.getType() != null || name != null && name.getImage().endsWith("executeQuery")) {
58                      ASTVariableDeclaratorId id = declarator.getFirstChildOfType(ASTVariableDeclaratorId.class);
59                      resultSetVariables.put(id.getImage(), node);
60                  }
61              }
62          }
63          return super.visit(node, data);
64      }
65  
66      @Override
67      public Object visit(ASTName node, Object data) {
68          String image = node.getImage();
69          String var = getResultSetVariableName(image);
70          if (var != null && resultSetVariables.containsKey(var)
71                  && node.getFirstParentOfType(ASTIfStatement.class) == null
72                  && node.getFirstParentOfType(ASTWhileStatement.class) == null
73                  && node.getFirstParentOfType(ASTReturnStatement.class) == null) {
74  
75              addViolation(data, resultSetVariables.get(var));
76          }
77          return super.visit(node, data);
78      }
79  
80      private String getResultSetVariableName(String image) {
81          if (image.contains(".")) {
82              for (String method : methods) {
83                  if (image.endsWith(method)) {
84                      return image.substring(0, image.lastIndexOf(method));
85                  }
86              }
87          }
88          return null;
89      }
90  }