/** * BSD-style license; for more info see http://pmd.sourceforge.net/license.html */ package net.sourceforge.pmd.lang.java.rule.logging; import java.util.Stack; import net.sourceforge.pmd.lang.ast.Node; import net.sourceforge.pmd.lang.java.ast.ASTAnnotationTypeDeclaration; import net.sourceforge.pmd.lang.java.ast.ASTClassOrInterfaceDeclaration; import net.sourceforge.pmd.lang.java.ast.ASTClassOrInterfaceType; import net.sourceforge.pmd.lang.java.ast.ASTEnumDeclaration; import net.sourceforge.pmd.lang.java.ast.ASTReferenceType; import net.sourceforge.pmd.lang.java.ast.ASTType; import net.sourceforge.pmd.lang.java.ast.ASTVariableDeclarator; import net.sourceforge.pmd.lang.java.ast.JavaNode; import net.sourceforge.pmd.lang.java.rule.AbstractJavaRule; import net.sourceforge.pmd.util.NumericConstants; public class MoreThanOneLoggerRule extends AbstractJavaRule { private static final Class<?> LOG4J_LOGGER; private static final Class<?> JAVA_LOGGER; private static final Class<?> SLF4J_LOGGER; static { Class<?> c; try { c = Class.forName("org.apache.log4j.Logger"); } catch (Throwable t) { c = null; } LOG4J_LOGGER = c; try { c = Class.forName("java.util.logging.Logger"); } catch (Throwable t) { c = null; } JAVA_LOGGER = c; try { c = Class.forName("org.slf4j.Logger"); } catch (Throwable t) { c = null; } SLF4J_LOGGER = c; } private Stack<Integer> stack = new Stack<>(); private Integer count; @Override public Object visit(ASTClassOrInterfaceDeclaration node, Object data) { return init(node, data); } @Override public Object visit(ASTEnumDeclaration node, Object data) { return init(node, data); } @Override public Object visit(ASTAnnotationTypeDeclaration node, Object data) { return init(node, data); } private Object init(JavaNode node, Object data) { stack.push(count); count = NumericConstants.ZERO; node.childrenAccept(this, data); if (count > 1) { addViolation(data, node); } count = stack.pop(); return data; } @Override public Object visit(ASTVariableDeclarator node, Object data) { if (count > 1) { return super.visit(node, data); } Node type = node.jjtGetParent().getFirstChildOfType(ASTType.class); if (type != null) { Node reftypeNode = type.jjtGetChild(0); if (reftypeNode instanceof ASTReferenceType) { Node classOrIntType = reftypeNode.jjtGetChild(0); if (classOrIntType instanceof ASTClassOrInterfaceType) { Class<?> clazzType = ((ASTClassOrInterfaceType) classOrIntType).getType(); if (clazzType != null && (clazzType.equals(LOG4J_LOGGER) || clazzType.equals(JAVA_LOGGER) || clazzType.equals(SLF4J_LOGGER)) || clazzType == null && "Logger".equals(classOrIntType.getImage())) { ++count; } } } } return super.visit(node, data); } }