KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > net > sourceforge > pmd > rules > DoubleCheckedLocking


1 /**
2  * BSD-style license; for more info see http://pmd.sourceforge.net/license.html
3  */

4 package net.sourceforge.pmd.rules;
5
6 import net.sourceforge.pmd.ast.ASTAssignmentOperator;
7 import net.sourceforge.pmd.ast.ASTClassOrInterfaceDeclaration;
8 import net.sourceforge.pmd.ast.ASTIfStatement;
9 import net.sourceforge.pmd.ast.ASTLiteral;
10 import net.sourceforge.pmd.ast.ASTMethodDeclaration;
11 import net.sourceforge.pmd.ast.ASTName;
12 import net.sourceforge.pmd.ast.ASTNullLiteral;
13 import net.sourceforge.pmd.ast.ASTPrimaryExpression;
14 import net.sourceforge.pmd.ast.ASTPrimaryPrefix;
15 import net.sourceforge.pmd.ast.ASTReferenceType;
16 import net.sourceforge.pmd.ast.ASTReturnStatement;
17 import net.sourceforge.pmd.ast.ASTStatementExpression;
18 import net.sourceforge.pmd.ast.ASTSynchronizedStatement;
19 import net.sourceforge.pmd.ast.ASTType;
20 import net.sourceforge.pmd.ast.Node;
21
22 import java.util.ArrayList JavaDoc;
23 import java.util.List JavaDoc;
24
25 /**
26  * void method() {
27  * if(x == null) {
28  * synchronized(this){
29  * if(x == null) {
30  * x = new | method();
31  * }
32  * }
33  * }
34  * 1. The error is when one uses the value assigned within a synchronized
35  * section, outside of a synchronized section.
36  * if(x == null) is outside of synchronized section
37  * x = new | method();
38  * <p/>
39  * <p/>
40  * Very very specific check for double checked locking.
41  *
42  * @author CL Gilbert (dnoyeb@users.sourceforge.net)
43  */

44 public class DoubleCheckedLocking extends net.sourceforge.pmd.AbstractRule {
45
46     public Object JavaDoc visit(ASTClassOrInterfaceDeclaration node, Object JavaDoc data) {
47         if (node.isInterface()) {
48             return data;
49         }
50         return super.visit(node, data);
51     }
52
53     public Object JavaDoc visit(ASTMethodDeclaration node, Object JavaDoc data) {
54         if (node.getResultType().isVoid()) {
55             return super.visit(node, data);
56         }
57
58         ASTType typeNode = (ASTType) node.getResultType().jjtGetChild(0);
59         if (typeNode.jjtGetNumChildren() == 0 || !(typeNode.jjtGetChild(0) instanceof ASTReferenceType)) {
60             return super.visit(node, data);
61         }
62
63         List JavaDoc finder = new ArrayList JavaDoc();
64         node.findChildrenOfType(ASTReturnStatement.class, finder, true);
65         if (finder.size() != 1) {
66             return super.visit(node, data);
67         }
68         ASTReturnStatement rs = (ASTReturnStatement) finder.get(0);
69
70         finder.clear();
71         rs.findChildrenOfType(ASTPrimaryExpression.class, finder, true);
72         ASTPrimaryExpression ape = (ASTPrimaryExpression) finder.get(0);
73         Node lastChild = ape.jjtGetChild(ape.jjtGetNumChildren() - 1);
74         String JavaDoc returnVariableName = null;
75         if (lastChild instanceof ASTPrimaryPrefix) {
76             returnVariableName = getNameFromPrimaryPrefix((ASTPrimaryPrefix) lastChild);
77         }
78         if (returnVariableName == null) {
79             return super.visit(node, data);
80         }
81         finder.clear();
82         node.findChildrenOfType(ASTIfStatement.class, finder, true);
83         if (finder.size() == 2) {
84             ASTIfStatement is = (ASTIfStatement) finder.get(0);
85             if (ifVerify(is, returnVariableName)) {
86                 //find synchronized
87
finder.clear();
88                 is.findChildrenOfType(ASTSynchronizedStatement.class, finder, true);
89                 if (finder.size() == 1) {
90                     ASTSynchronizedStatement ss = (ASTSynchronizedStatement) finder.get(0);
91                     finder.clear();
92                     ss.findChildrenOfType(ASTIfStatement.class, finder, true);
93                     if (finder.size() == 1) {
94                         ASTIfStatement is2 = (ASTIfStatement) finder.get(0);
95                         if (ifVerify(is2, returnVariableName)) {
96                             finder.clear();
97                             is2.findChildrenOfType(ASTStatementExpression.class, finder, true);
98                             if (finder.size() == 1) {
99                                 ASTStatementExpression se = (ASTStatementExpression) finder.get(0);
100                                 if (se.jjtGetNumChildren() == 3) { //primaryExpression, AssignmentOperator, Expression
101
if (se.jjtGetChild(0) instanceof ASTPrimaryExpression) {
102                                         ASTPrimaryExpression pe = (ASTPrimaryExpression) se.jjtGetChild(0);
103                                         if (matchName(pe, returnVariableName)) {
104                                             if (se.jjtGetChild(1) instanceof ASTAssignmentOperator) {
105                                                 addViolation(data, node);
106                                             }
107                                         }
108                                     }
109                                 }
110                             }
111                         }
112                     }
113                 }
114             }
115         }
116         return super.visit(node, data);
117     }
118
119     private boolean ifVerify(ASTIfStatement is, String JavaDoc varname) {
120         List JavaDoc finder = new ArrayList JavaDoc();
121         is.findChildrenOfType(ASTPrimaryExpression.class, finder, true);
122         if (finder.size() > 1) {
123             ASTPrimaryExpression apeLeft = (ASTPrimaryExpression) finder.get(0);
124             if (matchName(apeLeft, varname)) {
125                 ASTPrimaryExpression apeRight = (ASTPrimaryExpression) finder.get(1);
126                 if ((apeRight.jjtGetNumChildren() == 1) && (apeRight.jjtGetChild(0) instanceof ASTPrimaryPrefix)) {
127                     ASTPrimaryPrefix pp2 = (ASTPrimaryPrefix) apeRight.jjtGetChild(0);
128                     if ((pp2.jjtGetNumChildren() == 1) && (pp2.jjtGetChild(0) instanceof ASTLiteral)) {
129                         ASTLiteral lit = (ASTLiteral) pp2.jjtGetChild(0);
130                         if ((lit.jjtGetNumChildren() == 1) && (lit.jjtGetChild(0) instanceof ASTNullLiteral)) {
131                             return true;
132                         }
133                     }
134                 }
135             }
136         }
137         return false;
138     }
139
140     private boolean matchName(ASTPrimaryExpression ape, String JavaDoc name) {
141         if ((ape.jjtGetNumChildren() == 1) && (ape.jjtGetChild(0) instanceof ASTPrimaryPrefix)) {
142             ASTPrimaryPrefix pp = (ASTPrimaryPrefix) ape.jjtGetChild(0);
143             String JavaDoc name2 = getNameFromPrimaryPrefix(pp);
144             if (name2 != null && name2.equals(name)) {
145                 return true;
146             }
147         }
148         return false;
149     }
150
151     private String JavaDoc getNameFromPrimaryPrefix(ASTPrimaryPrefix pp) {
152         if ((pp.jjtGetNumChildren() == 1) && (pp.jjtGetChild(0) instanceof ASTName)) {
153             return ((ASTName) pp.jjtGetChild(0)).getImage();
154         }
155         return null;
156     }
157 }
158
Popular Tags