1
2
3
4 package net.sourceforge.pmd.lang.java.rule.logging;
5
6 import java.util.ArrayList;
7 import java.util.Arrays;
8 import java.util.Collections;
9 import java.util.HashMap;
10 import java.util.List;
11 import java.util.Map;
12 import java.util.Map.Entry;
13
14 import net.sourceforge.pmd.Rule;
15 import net.sourceforge.pmd.lang.ast.Node;
16 import net.sourceforge.pmd.lang.java.ast.ASTCompilationUnit;
17 import net.sourceforge.pmd.lang.java.rule.optimizations.AbstractOptimizationRule;
18 import net.sourceforge.pmd.lang.rule.properties.StringMultiProperty;
19
20 import org.jaxen.JaxenException;
21
22
23
24
25
26
27
28
29
30
31 public class GuardLogStatementRule extends AbstractOptimizationRule implements Rule {
32
33 public static final StringMultiProperty LOG_LEVELS = new StringMultiProperty("logLevels", "LogLevels to guard",
34 new String[] {}, 1.0f, ',');
35
36 public static final StringMultiProperty GUARD_METHODS = new StringMultiProperty("guardsMethods",
37 "method use to guard the log statement", new String[] {}, 2.0f, ',');
38
39 protected Map<String, String> guardStmtByLogLevel = new HashMap<String, String>(5);
40
41 private static final String XPATH_EXPRESSION = "//PrimaryPrefix[ends-with(Name/@Image, 'LOG_LEVEL')]"
42 + "[count(../descendant::AdditiveExpression) > 0]"
43 + "[count(ancestor::IfStatement/Expression/descendant::PrimaryExpression["
44 + "ends-with(descendant::PrimaryPrefix/Name/@Image,'GUARD')]) = 0]";
45
46 public GuardLogStatementRule() {
47 definePropertyDescriptor(LOG_LEVELS);
48 definePropertyDescriptor(GUARD_METHODS);
49 }
50
51 @Override
52 public Object visit(ASTCompilationUnit unit, Object data) {
53 extractProperties();
54 findViolationForEachLogStatement(unit, data, XPATH_EXPRESSION);
55 return super.visit(unit, data);
56 }
57
58 protected void findViolationForEachLogStatement(ASTCompilationUnit unit, Object data, String xpathExpression) {
59 for (Entry<String, String> entry : guardStmtByLogLevel.entrySet()) {
60 List<Node> nodes = findViolations(unit, entry.getKey(), entry.getValue(), xpathExpression);
61 for (Node node : nodes) {
62 super.addViolation(data, node);
63 }
64 }
65 }
66
67 @SuppressWarnings("unchecked")
68 private List<Node> findViolations(ASTCompilationUnit unit, String logLevel, String guard, String xpathExpression) {
69 try {
70 return unit.findChildNodesWithXPath(xpathExpression
71 .replaceAll("LOG_LEVEL_UPPERCASE", logLevel.toUpperCase()).replaceAll("LOG_LEVEL", logLevel)
72 .replaceAll("GUARD", guard));
73 } catch (JaxenException e) {
74 e.printStackTrace();
75 }
76 return Collections.EMPTY_LIST;
77 }
78
79 private void setPropertiesDefaultValues(List<String> logLevels, List<String> guardMethods) {
80 logLevels.add("trace");
81 logLevels.add("debug");
82 logLevels.add("info");
83 logLevels.add("warn");
84 logLevels.add("error");
85
86 guardMethods.clear();
87 guardMethods.add("isTraceEnabled");
88 guardMethods.add("isDebugEnabled");
89 guardMethods.add("isInfoEnabled");
90 guardMethods.add("isWarnEnabled");
91 guardMethods.add("isErrorEnabled");
92 }
93
94 protected void extractProperties() {
95 if (guardStmtByLogLevel.isEmpty()) {
96
97 List<String> logLevels = new ArrayList<String>(Arrays.asList(super.getProperty(LOG_LEVELS)));
98 List<String> guardMethods = new ArrayList<String>(Arrays.asList(super.getProperty(GUARD_METHODS)));
99
100 if (guardMethods.isEmpty() && !logLevels.isEmpty()) {
101 throw new IllegalArgumentException("Can't specify guardMethods without specifiying logLevels.");
102 }
103
104 if (logLevels.isEmpty()) {
105 setPropertiesDefaultValues(logLevels, guardMethods);
106 }
107
108 buildGuardStatementMap(logLevels, guardMethods);
109 }
110 }
111
112 protected void buildGuardStatementMap(List<String> logLevels, List<String> guardMethods) {
113 for (String logLevel : logLevels) {
114 boolean found = false;
115 for (String guardMethod : guardMethods) {
116 if (!found && guardMethod.toLowerCase().contains(logLevel.toLowerCase())) {
117 found = true;
118 guardStmtByLogLevel.put("." + logLevel, guardMethod);
119 }
120 }
121
122 if (!found) {
123 throw new IllegalArgumentException("No guard method associated to the logLevel:" + logLevel
124 + ". Should be something like 'is" + logLevel + "Enabled'.");
125 }
126 }
127 }
128 }