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.logging;
5   
6   import java.util.Stack;
7   
8   import net.sourceforge.pmd.lang.ast.Node;
9   import net.sourceforge.pmd.lang.java.ast.ASTAnnotationTypeDeclaration;
10  import net.sourceforge.pmd.lang.java.ast.ASTClassOrInterfaceDeclaration;
11  import net.sourceforge.pmd.lang.java.ast.ASTClassOrInterfaceType;
12  import net.sourceforge.pmd.lang.java.ast.ASTEnumDeclaration;
13  import net.sourceforge.pmd.lang.java.ast.ASTReferenceType;
14  import net.sourceforge.pmd.lang.java.ast.ASTType;
15  import net.sourceforge.pmd.lang.java.ast.ASTVariableDeclarator;
16  import net.sourceforge.pmd.lang.java.ast.JavaNode;
17  import net.sourceforge.pmd.lang.java.rule.AbstractJavaRule;
18  import net.sourceforge.pmd.util.NumericConstants;
19  
20  public class MoreThanOneLoggerRule extends AbstractJavaRule {
21  
22      private static final Class<?> LOG4J_LOGGER;
23  
24      private static final Class<?> JAVA_LOGGER;
25      
26      private static final Class<?> SLF4J_LOGGER;
27  
28      static {
29  	Class<?> c;
30  	try {
31  	    c = Class.forName("org.apache.log4j.Logger");
32  	} catch (Throwable t) {
33  	    c = null;
34  	}
35  	LOG4J_LOGGER = c;
36  	try {
37  	    c = Class.forName("java.util.logging.Logger");
38  	} catch (Throwable t) {
39  	    c = null;
40  	}
41  	JAVA_LOGGER = c;
42  	try {
43  	    c = Class.forName("org.slf4j.Logger");
44  	} catch (Throwable t) {
45  	    c = null;
46  	}
47  	SLF4J_LOGGER = c;
48      }
49  
50      private Stack<Integer> stack = new Stack<Integer>();
51  
52      private Integer count;
53  
54      @Override
55      public Object visit(ASTClassOrInterfaceDeclaration node, Object data) {
56  	return init(node, data);
57      }
58  
59      @Override
60      public Object visit(ASTEnumDeclaration node, Object data) {
61  	return init(node, data);
62      }
63  
64      @Override
65      public Object visit(ASTAnnotationTypeDeclaration node, Object data) {
66  	return init(node, data);
67      }
68  
69      private Object init(JavaNode node, Object data) {
70  	stack.push(count);
71  	count = NumericConstants.ZERO;
72  
73  	node.childrenAccept(this, data);
74  
75  	if (count > 1) {
76  	    addViolation(data, node);
77  	}
78  	count = stack.pop();
79  
80  	return data;
81      }
82  
83      @Override
84      public Object visit(ASTVariableDeclarator node, Object data) {
85  	if (count > 1) {
86  	    return super.visit(node, data);
87  	}
88  	Node type = node.jjtGetParent().getFirstChildOfType(ASTType.class);
89  	if (type != null) {
90  	    Node reftypeNode = type.jjtGetChild(0);
91  	    if (reftypeNode instanceof ASTReferenceType) {
92  		Node classOrIntType = reftypeNode.jjtGetChild(0);
93  		if (classOrIntType instanceof ASTClassOrInterfaceType) {
94  		    Class<?> clazzType = ((ASTClassOrInterfaceType) classOrIntType).getType();
95  		    if (clazzType != null && (clazzType.equals(LOG4J_LOGGER) 
96  		                           || clazzType.equals(JAVA_LOGGER) 
97  		                           || clazzType.equals(SLF4J_LOGGER))
98  			    || clazzType == null && "Logger".equals(classOrIntType.getImage())) {
99  			++count;
100 		    }
101 		}
102 	    }
103 	}
104 
105 	return super.visit(node, data);
106     }
107 
108 }