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.sunsecure;
5   
6   import java.util.List;
7   
8   import net.sourceforge.pmd.lang.ast.Node;
9   import net.sourceforge.pmd.lang.java.ast.ASTConditionalExpression;
10  import net.sourceforge.pmd.lang.java.ast.ASTEqualityExpression;
11  import net.sourceforge.pmd.lang.java.ast.ASTFieldDeclaration;
12  import net.sourceforge.pmd.lang.java.ast.ASTLocalVariableDeclaration;
13  import net.sourceforge.pmd.lang.java.ast.ASTName;
14  import net.sourceforge.pmd.lang.java.ast.ASTNullLiteral;
15  import net.sourceforge.pmd.lang.java.ast.ASTPrimarySuffix;
16  import net.sourceforge.pmd.lang.java.ast.ASTReturnStatement;
17  import net.sourceforge.pmd.lang.java.ast.ASTTypeDeclaration;
18  import net.sourceforge.pmd.lang.java.ast.ASTVariableDeclaratorId;
19  import net.sourceforge.pmd.lang.java.rule.AbstractJavaRule;
20  
21  /**
22   * Utility methods for the package
23   *
24   * Created on Jan 17, 2005
25   * 
26   * @author mgriffa
27   */
28  public abstract class AbstractSunSecureRule extends AbstractJavaRule {
29  
30      /**
31       * Tells if the type declaration has a field with varName.
32       *
33       * @param varName
34       *            the name of the field to search
35       * @param typeDeclaration
36       *            the type declaration
37       * @return <code>true</code> if there is a field in the type declaration
38       *         named varName, <code>false</code> in other case
39       */
40      protected final boolean isField(String varName, ASTTypeDeclaration typeDeclaration) {
41          final List<ASTFieldDeclaration> fds = typeDeclaration.findDescendantsOfType(ASTFieldDeclaration.class);
42          if (fds != null) {
43              for (ASTFieldDeclaration fd : fds) {
44                  final ASTVariableDeclaratorId vid = fd.getFirstDescendantOfType(ASTVariableDeclaratorId.class);
45                  if (vid != null && vid.hasImageEqualTo(varName)) {
46                      return true;
47                  }
48              }
49          }
50          return false;
51      }
52  
53      /**
54       * Gets the name of the variable returned. Some examples: <br>
55       * for this.foo returns foo <br>
56       * for foo returns foo <br>
57       * for foo.bar returns foo.bar
58       *
59       * @param ret
60       *            a return statement to evaluate
61       * @return the name of the variable associated or <code>null</code> if it
62       *         cannot be detected
63       */
64      protected final String getReturnedVariableName(ASTReturnStatement ret) {
65          if (hasTernaryCondition(ret) && hasTernaryNullCheck(ret)) {
66              return ret.getFirstDescendantOfType(ASTConditionalExpression.class).jjtGetChild(0)
67                          .getFirstDescendantOfType(ASTName.class).getImage();
68          }
69  
70          final ASTName n = ret.getFirstDescendantOfType(ASTName.class);
71          if (n != null) {
72              return n.getImage();
73          }
74          final ASTPrimarySuffix ps = ret.getFirstDescendantOfType(ASTPrimarySuffix.class);
75          if (ps != null) {
76              return ps.getImage();
77          }
78          return null;
79      }
80  
81      private boolean hasTernaryNullCheck(ASTReturnStatement ret) {
82          ASTConditionalExpression condition = ret.getFirstDescendantOfType(ASTConditionalExpression.class);
83          return condition.jjtGetChild(0) instanceof ASTEqualityExpression
84                  && condition.jjtGetChild(0).hasImageEqualTo("==")
85                  && condition.jjtGetChild(0).jjtGetChild(0).hasDescendantOfType(ASTName.class)
86                  && condition.jjtGetChild(0).jjtGetChild(1).hasDescendantOfType(ASTNullLiteral.class);
87      }
88  
89      private boolean hasTernaryCondition(ASTReturnStatement ret) {
90          ASTConditionalExpression condition = ret.getFirstDescendantOfType(ASTConditionalExpression.class);
91          return condition != null && condition.isTernary();
92      }
93  
94      /**
95       * TODO modify usages to use symbol table Tells if the variable name is a
96       * local variable declared in the method.
97       *
98       * @param vn
99       *            the variable name
100      * @param node
101      *            the ASTMethodDeclaration where the local variable name will be
102      *            searched
103      * @return <code>true</code> if the method declaration contains any local
104      *         variable named vn and <code>false</code> in other case
105      */
106     protected boolean isLocalVariable(String vn, Node node) {
107         final List<ASTLocalVariableDeclaration> lvars = node.findDescendantsOfType(ASTLocalVariableDeclaration.class);
108         if (lvars != null) {
109             for (ASTLocalVariableDeclaration lvd : lvars) {
110                 final ASTVariableDeclaratorId vid = lvd.getFirstDescendantOfType(ASTVariableDeclaratorId.class);
111                 if (vid != null && vid.hasImageEqualTo(vn)) {
112                     return true;
113                 }
114             }
115         }
116         return false;
117     }
118 
119     /**
120      * Gets the image of the first ASTName node found by
121      * {@link Node#getFirstDescendantOfType(Class)}
122      *
123      * @param n
124      *            the node to search
125      * @return the image of the first ASTName or <code>null</code>
126      */
127     protected String getFirstNameImage(Node n) {
128         ASTName name = n.getFirstDescendantOfType(ASTName.class);
129         if (name != null) {
130             return name.getImage();
131         }
132         return null;
133     }
134 
135 }