Clover coverage report - PMD - 3.7
Coverage timestamp: Wed May 31 2006 09:25:59 EDT
file stats: LOC: 63   Methods: 1
NCLOC: 42   Classes: 1
 
 Source file Conditionals Statements Methods TOTAL
UnsynchronizedStaticDateFormatter.java 90% 94.7% 100% 93.3%
coverage coverage
 1    /**
 2    * BSD-style license; for more info see http://pmd.sourceforge.net/license.html
 3    */
 4    package net.sourceforge.pmd.rules.design;
 5   
 6    import net.sourceforge.pmd.AbstractRule;
 7    import net.sourceforge.pmd.ast.ASTClassOrInterfaceType;
 8    import net.sourceforge.pmd.ast.ASTFieldDeclaration;
 9    import net.sourceforge.pmd.ast.ASTMethodDeclaration;
 10    import net.sourceforge.pmd.ast.ASTSynchronizedStatement;
 11    import net.sourceforge.pmd.ast.ASTVariableDeclaratorId;
 12    import net.sourceforge.pmd.ast.SimpleNode;
 13    import net.sourceforge.pmd.symboltable.NameOccurrence;
 14   
 15    import java.util.HashSet;
 16    import java.util.Iterator;
 17    import java.util.Set;
 18   
 19    /**
 20    * Using a DateFormatter (SimpleDateFormatter) which is static can cause
 21    * unexpected results when used in a multi threaded environment. This rule will
 22    * find static (Simple)DateFormatters which are used in an unsynchronized
 23    * manner.
 24    *
 25    * @link http://developer.java.sun.com/developer/bugParade/bugs/4093418.html
 26    * @link http://developer.java.sun.com/developer/bugParade/bugs/4228335.html
 27    * @link http://developer.java.sun.com/developer/bugParade/bugs/4261469.html
 28    * @see RFE1020790 - Check for SimpleDateFormat as singleton http://sourceforge.net/tracker/index.php?func=detail&aid=1020790&group_id=56262&atid=479924
 29    * @author Allan Caplan
 30    */
 31    public class UnsynchronizedStaticDateFormatter extends AbstractRule {
 32   
 33    private static Set targets = new HashSet();
 34    static {
 35  38 targets.add("DateFormat");
 36  38 targets.add("SimpleDateFormat");
 37  38 targets.add("java.text.DateFormat");
 38  38 targets.add("java.text.SimpleDateFormat");
 39    }
 40   
 41  6 public Object visit(ASTFieldDeclaration node, Object data) {
 42  6 if (!node.isStatic()) {
 43  1 return data;
 44    }
 45  5 ASTClassOrInterfaceType cit = (ASTClassOrInterfaceType) node.getFirstChildOfType(ASTClassOrInterfaceType.class);
 46  5 if (cit == null || !targets.contains(cit.getImage())) {
 47  0 return data;
 48    }
 49  5 ASTVariableDeclaratorId var = (ASTVariableDeclaratorId) node.getFirstChildOfType(ASTVariableDeclaratorId.class);
 50  5 for (Iterator i = var.getUsages().iterator(); i.hasNext();) {
 51  6 NameOccurrence occ = (NameOccurrence) i.next();
 52  6 SimpleNode n = occ.getLocation();
 53  6 if ((ASTSynchronizedStatement) n.getFirstParentOfType(ASTSynchronizedStatement.class) != null) {
 54  2 continue;
 55    }
 56  4 ASTMethodDeclaration method = (ASTMethodDeclaration) n.getFirstParentOfType(ASTMethodDeclaration.class);
 57  4 if (method != null && !method.isSynchronized()) {
 58  2 addViolation(data, n);
 59    }
 60    }
 61  5 return data;
 62    }
 63    }