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
32 Rule {
33
34 public static final StringMultiProperty LOG_LEVELS = new StringMultiProperty(
35 "logLevels", "LogLevels to guard", new String[] {}, 1.0f, ',');
36
37 public static final StringMultiProperty GUARD_METHODS = new StringMultiProperty(
38 "guardsMethods", "method use to guard the log statement",
39 new String[] {}, 2.0f, ',');
40
41 protected Map<String, String> guardStmtByLogLevel = new HashMap<String, String>(
42 5);
43
44 private static final String xpathExpression = "//PrimaryPrefix[ends-with(Name/@Image, 'KEY') and "
45 + "count("
46 + "ancestor::IfStatement/Expression/descendant::PrimaryExpression["
47 + "ends-with(descendant::PrimaryPrefix/Name/@Image,'VALUE')]) = 0]";
48
49 public GuardLogStatementRule() {
50 definePropertyDescriptor(LOG_LEVELS);
51 definePropertyDescriptor(GUARD_METHODS);
52 }
53
54 @Override
55 public Object visit(ASTCompilationUnit unit, Object data) {
56 extractProperties();
57 findViolationForEachLogStatement(unit, data);
58 return super.visit(unit, data);
59 }
60
61 private void findViolationForEachLogStatement(ASTCompilationUnit unit, Object data) {
62 for (Entry<String, String> entry : guardStmtByLogLevel.entrySet()) {
63 List<Node> nodes = findViolations(unit, entry.getKey(),
64 entry.getValue());
65 for (Node node : nodes) {
66 super.addViolation(data, node);
67 }
68 }
69 }
70
71 @SuppressWarnings("unchecked")
72 private List<Node> findViolations(ASTCompilationUnit unit, String key,
73 String value) {
74 try {
75 return unit.findChildNodesWithXPath(xpathExpression.replaceFirst(
76 "KEY", key).replaceFirst("VALUE", value));
77 } catch (JaxenException e) {
78 e.printStackTrace();
79 }
80 return Collections.EMPTY_LIST;
81 }
82
83 private void setPropertiesDefaultValues(List<String> logLevels,
84 List<String> guardMethods) {
85 logLevels.add("trace");
86 logLevels.add("debug");
87 logLevels.add("info");
88 logLevels.add("warn");
89 logLevels.add("error");
90
91 guardMethods.clear();
92 guardMethods.add("isTraceEnabled");
93 guardMethods.add("isDebugEnabled");
94 guardMethods.add("isInfoEnabled");
95 guardMethods.add("isWarnEnabled");
96 guardMethods.add("isErrorEnabled");
97 }
98
99 protected void extractProperties() {
100 if (guardStmtByLogLevel.isEmpty()) {
101
102 List<String> logLevels = new ArrayList<String>(Arrays.asList(super
103 .getProperty(LOG_LEVELS)));
104 List<String> guardMethods = new ArrayList<String>(
105 Arrays.asList(super.getProperty(GUARD_METHODS)));
106
107 if (guardMethods.isEmpty() && !logLevels.isEmpty()) {
108 throw new IllegalArgumentException(
109 "Can't specify guardMethods without specifiying logLevels.");
110 }
111
112 if (logLevels.isEmpty())
113 setPropertiesDefaultValues(logLevels, guardMethods);
114
115 buildGuardStatementMap(logLevels, guardMethods);
116 }
117 }
118
119 protected void buildGuardStatementMap(List<String> logLevels,
120 List<String> guardMethods) {
121 for (String logLevel : logLevels) {
122 boolean found = false;
123 for (String guardMethod : guardMethods) {
124 if (!found
125 && guardMethod.toLowerCase().contains(
126 logLevel.toLowerCase())) {
127 found = true;
128 guardStmtByLogLevel.put("." + logLevel, guardMethod);
129 }
130 }
131
132 if (!found)
133 throw new IllegalArgumentException(
134 "No guard method associated to the logLevel:"
135 + logLevel + ". Should be something like 'is"
136 + logLevel + "Enabled'.");
137 }
138 }
139 }