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