01: /**
02: * BSD-style license; for more info see http://pmd.sourceforge.net/license.html
03: */package net.sourceforge.pmd.rules.design;
04:
05: import net.sourceforge.pmd.AbstractRule;
06: import net.sourceforge.pmd.ast.ASTClassOrInterfaceType;
07: import net.sourceforge.pmd.ast.ASTFieldDeclaration;
08: import net.sourceforge.pmd.ast.ASTMethodDeclaration;
09: import net.sourceforge.pmd.ast.ASTSynchronizedStatement;
10: import net.sourceforge.pmd.ast.ASTVariableDeclaratorId;
11: import net.sourceforge.pmd.ast.SimpleNode;
12: import net.sourceforge.pmd.symboltable.NameOccurrence;
13:
14: import java.util.HashSet;
15: import java.util.Set;
16:
17: /**
18: * Using a DateFormatter (SimpleDateFormatter) which is static can cause
19: * unexpected results when used in a multi threaded environment. This rule will
20: * find static (Simple)DateFormatters which are used in an unsynchronized
21: * manner.
22: * Refer to these Bug Parade issues:
23: * <a href="http://developer.java.sun.com/developer/bugParade/bugs/4093418.html">4093418</a>
24: * <a href="http://developer.java.sun.com/developer/bugParade/bugs/4228335.html">4228335</a>
25: * <a href="http://developer.java.sun.com/developer/bugParade/bugs/4261469.html">4261469</a>
26: * see RFE1020790 - Check for SimpleDateFormat as singleton http://sourceforge.net/tracker/index.php?func=detail&aid=1020790&group_id=56262&atid=479924
27: * @author Allan Caplan
28: */
29: public class UnsynchronizedStaticDateFormatter extends AbstractRule {
30:
31: private static Set<String> targets = new HashSet<String>();
32: static {
33: targets.add("DateFormat");
34: targets.add("SimpleDateFormat");
35: targets.add("java.text.DateFormat");
36: targets.add("java.text.SimpleDateFormat");
37: }
38:
39: public Object visit(ASTFieldDeclaration node, Object data) {
40: if (!node.isStatic()) {
41: return data;
42: }
43: ASTClassOrInterfaceType cit = node
44: .getFirstChildOfType(ASTClassOrInterfaceType.class);
45: if (cit == null || !targets.contains(cit.getImage())) {
46: return data;
47: }
48: ASTVariableDeclaratorId var = node
49: .getFirstChildOfType(ASTVariableDeclaratorId.class);
50: for (NameOccurrence occ : var.getUsages()) {
51: SimpleNode n = occ.getLocation();
52: if (n.getFirstParentOfType(ASTSynchronizedStatement.class) != null) {
53: continue;
54: }
55: ASTMethodDeclaration method = n
56: .getFirstParentOfType(ASTMethodDeclaration.class);
57: if (method != null && !method.isSynchronized()) {
58: addViolation(data, n);
59: }
60: }
61: return data;
62: }
63: }
|