KickJava   Java API By Example, From Geeks To Geeks.

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


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.AbstractRule;
7 import net.sourceforge.pmd.PropertyDescriptor;
8 import net.sourceforge.pmd.ast.ASTBlock;
9 import net.sourceforge.pmd.ast.ASTClassOrInterfaceType;
10 import net.sourceforge.pmd.ast.ASTCompilationUnit;
11 import net.sourceforge.pmd.ast.ASTLocalVariableDeclaration;
12 import net.sourceforge.pmd.ast.ASTMethodDeclaration;
13 import net.sourceforge.pmd.ast.ASTName;
14 import net.sourceforge.pmd.ast.ASTReferenceType;
15 import net.sourceforge.pmd.ast.ASTTryStatement;
16 import net.sourceforge.pmd.ast.ASTType;
17 import net.sourceforge.pmd.ast.ASTVariableDeclaratorId;
18 import net.sourceforge.pmd.ast.Node;
19 import net.sourceforge.pmd.properties.StringProperty;
20
21 import java.util.ArrayList JavaDoc;
22 import java.util.HashSet JavaDoc;
23 import java.util.Iterator JavaDoc;
24 import java.util.List JavaDoc;
25 import java.util.Map JavaDoc;
26 import java.util.Set JavaDoc;
27 import java.util.StringTokenizer JavaDoc;
28
29 /**
30  * Makes sure you close your database connections. It does this by
31  * looking for code patterned like this:
32  * <pre>
33  * Connection c = X;
34  * try {
35  * // do stuff, and maybe catch something
36  * } finally {
37  * c.close();
38  * }
39  * </pre>
40  */

41 public class CloseResource extends AbstractRule {
42
43     private Set JavaDoc types = new HashSet JavaDoc();
44     
45
46     private Set JavaDoc closeTargets = new HashSet JavaDoc();
47     private static final PropertyDescriptor closeTargetsDescriptor = new StringProperty("closeTargets",
48             "Methods which may close this resource", "", 1.0f);
49
50     private static final PropertyDescriptor typesDescriptor = new StringProperty("types",
51             "Types that are affected by this rule", "", 2.0f);
52
53     private static final Map JavaDoc propertyDescriptorsByName = asFixedMap(new PropertyDescriptor[] { typesDescriptor, closeTargetsDescriptor });
54
55     protected Map JavaDoc propertiesByName() {
56         return propertyDescriptorsByName;
57     };
58
59     public Object JavaDoc visit(ASTCompilationUnit node, Object JavaDoc data) {
60         if (closeTargets.isEmpty() && getStringProperty(closeTargetsDescriptor) != null) {
61             for (StringTokenizer JavaDoc st = new StringTokenizer JavaDoc(getStringProperty(closeTargetsDescriptor), ","); st.hasMoreTokens();) {
62                 closeTargets.add(st.nextToken());
63             }
64         }
65         if (types.isEmpty() && getStringProperty(typesDescriptor) != null) {
66             for (StringTokenizer JavaDoc st = new StringTokenizer JavaDoc(getStringProperty(typesDescriptor), ","); st.hasMoreTokens();) {
67                 types.add(st.nextToken());
68             }
69         }
70         return super.visit(node, data);
71     }
72
73     public Object JavaDoc visit(ASTMethodDeclaration node, Object JavaDoc data) {
74         List JavaDoc vars = node.findChildrenOfType(ASTLocalVariableDeclaration.class);
75         List JavaDoc ids = new ArrayList JavaDoc();
76
77         // find all variable references to Connection objects
78
for (Iterator JavaDoc it = vars.iterator(); it.hasNext();) {
79             ASTLocalVariableDeclaration var = (ASTLocalVariableDeclaration) it.next();
80             ASTType type = var.getTypeNode();
81
82             if (type.jjtGetChild(0) instanceof ASTReferenceType) {
83                 ASTReferenceType ref = (ASTReferenceType) type.jjtGetChild(0);
84                 if (ref.jjtGetChild(0) instanceof ASTClassOrInterfaceType) {
85                     ASTClassOrInterfaceType clazz = (ASTClassOrInterfaceType) ref.jjtGetChild(0);
86                     if (types.contains(clazz.getImage())) {
87                         ASTVariableDeclaratorId id = (ASTVariableDeclaratorId) var.jjtGetChild(1).jjtGetChild(0);
88                         ids.add(id);
89                     }
90                 }
91             }
92         }
93
94         // if there are connections, ensure each is closed.
95
for (int i = 0; i < ids.size(); i++) {
96             ASTVariableDeclaratorId x = (ASTVariableDeclaratorId) ids.get(i);
97             ensureClosed((ASTLocalVariableDeclaration) x.jjtGetParent().jjtGetParent(), x, data);
98         }
99         return data;
100     }
101
102     private void ensureClosed(ASTLocalVariableDeclaration var,
103                               ASTVariableDeclaratorId id, Object JavaDoc data) {
104         // What are the chances of a Connection being instantiated in a
105
// for-loop init block? Anyway, I'm lazy!
106
String JavaDoc target = id.getImage() + ".close";
107         Node n = var;
108
109         while (!((n = n.jjtGetParent()) instanceof ASTBlock)) ;
110
111         ASTBlock top = (ASTBlock) n;
112
113         List JavaDoc tryblocks = new ArrayList JavaDoc();
114         top.findChildrenOfType(ASTTryStatement.class, tryblocks, true);
115
116         boolean closed = false;
117
118         // look for try blocks below the line the variable was
119
// introduced and make sure there is a .close call in a finally
120
// block.
121
for (Iterator JavaDoc it = tryblocks.iterator(); it.hasNext();) {
122             ASTTryStatement t = (ASTTryStatement) it.next();
123
124             if ((t.getBeginLine() > id.getBeginLine()) && (t.hasFinally())) {
125                 ASTBlock f = (ASTBlock) t.getFinally().jjtGetChild(0);
126                 List JavaDoc names = new ArrayList JavaDoc();
127                 f.findChildrenOfType(ASTName.class, names, true);
128                 for (Iterator JavaDoc it2 = names.iterator(); it2.hasNext();) {
129                     String JavaDoc name = ((ASTName) it2.next()).getImage();
130                     if (name.equals(target) || closeTargets.contains(name)) {
131                         closed = true;
132                     }
133                 }
134             }
135         }
136
137         // if all is not well, complain
138
if (!closed) {
139             ASTType type = (ASTType) var.jjtGetChild(0);
140             ASTReferenceType ref = (ASTReferenceType) type.jjtGetChild(0);
141             ASTClassOrInterfaceType clazz = (ASTClassOrInterfaceType) ref.jjtGetChild(0);
142             addViolation(data, id, clazz.getImage());
143         }
144     }
145 }
146
Popular Tags