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