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.List;
7   import java.util.logging.Level;
8   
9   import net.sourceforge.pmd.lang.java.ast.ASTCompilationUnit;
10  import net.sourceforge.pmd.lang.java.ast.ASTImportDeclaration;
11  
12  public class GuardLogStatementJavaUtilRule extends GuardLogStatementRule {
13  
14  	private static final String GUARD_METHOD_NAME = "isLoggable";
15  
16  	private static String extendedXPath = "//PrimaryPrefix[ends-with(Name/@Image, '.log')]\n" + 
17  	        "[following-sibling::PrimarySuffix\n" + 
18  	        "    [ends-with(.//PrimaryPrefix/Name/@Image, 'LOG_LEVEL_UPPERCASE')]\n" + 
19  	        "    [count(../descendant::AdditiveExpression) > 0]\n" + 
20  	        "]\n" + 
21  	        "[count(ancestor::IfStatement/Expression/descendant::PrimaryExpression\n" + 
22  	        "    [ends-with(descendant::PrimaryPrefix[1]/Name/@Image,'GUARD')]) = 0\n" + 
23  	        "or\n" + 
24  	        "count(ancestor::IfStatement/Expression/descendant::PrimaryExpression\n" + 
25  	        "    [ends-with(descendant::PrimaryPrefix[2]/Name/@Image,'LOG_LEVEL_UPPERCASE')]) = 0]";
26  	
27  	@Override
28  	public Object visit(ASTCompilationUnit unit, Object data) {
29  	    if (isSlf4jOrLog4jImported(unit)) {
30  	        return data;
31  	    }
32  
33  	    String[] logLevels = getProperty(LOG_LEVELS);
34  	    String[] guardMethods = getProperty(GUARD_METHODS);
35  
36          if (super.guardStmtByLogLevel.isEmpty() && logLevels.length > 0 && guardMethods.length > 0) {
37              configureGuards(logLevels, guardMethods);
38          } else if ( super.guardStmtByLogLevel.isEmpty() ) {
39              configureDefaultGuards();
40          }
41  
42          findViolationForEachLogStatement(unit, data, extendedXPath);
43  		return super.visit(unit,data);
44  	}
45  
46      private boolean isSlf4jOrLog4jImported(ASTCompilationUnit unit) {
47          List<ASTImportDeclaration> imports = unit.findChildrenOfType(ASTImportDeclaration.class);
48          for (ASTImportDeclaration i : imports) {
49              if (i.getImportedName().startsWith("org.slf4j") || i.getImportedName().startsWith("org.apache.log4j")) {
50                  return true;
51              }
52          }
53          return false;
54      }
55  
56      private void configureGuards(String[] logLevels, String[] guardMethods) {
57          String[] methods = guardMethods;
58          if (methods.length != logLevels.length) {
59              String firstMethodName = guardMethods[0];
60              methods = new String[logLevels.length];
61              for (int i = 0; i < logLevels.length; i++) {
62                  methods[i] = firstMethodName;
63              }
64          }
65          for (int i = 0; i < logLevels.length; i++) {
66              super.guardStmtByLogLevel.put("." + logLevels[i], methods[i]);
67          }
68      }
69  
70      private void configureDefaultGuards() {
71          super.guardStmtByLogLevel.put(formatLogLevelString(Level.FINEST), GUARD_METHOD_NAME);
72          super.guardStmtByLogLevel.put(formatLogLevelString(Level.FINER), GUARD_METHOD_NAME);
73          super.guardStmtByLogLevel.put(formatLogLevelString(Level.FINE), GUARD_METHOD_NAME);
74          super.guardStmtByLogLevel.put(formatLogLevelString(Level.INFO), GUARD_METHOD_NAME);
75          super.guardStmtByLogLevel.put(formatLogLevelString(Level.WARNING), GUARD_METHOD_NAME);
76          super.guardStmtByLogLevel.put(formatLogLevelString(Level.SEVERE), GUARD_METHOD_NAME);
77      }
78  
79  	private String formatLogLevelString(Level logLevel) {
80  		return "." + logLevel.toString().toLowerCase();
81  	}
82  }