1
2
3
4 package net.sourceforge.pmd.renderers;
5
6 import java.io.IOException;
7 import java.io.Writer;
8 import java.util.Iterator;
9 import java.util.List;
10
11 import net.sourceforge.pmd.PMD;
12 import net.sourceforge.pmd.Report;
13 import net.sourceforge.pmd.RuleViolation;
14 import net.sourceforge.pmd.lang.rule.properties.StringProperty;
15 import net.sourceforge.pmd.util.StringUtil;
16
17
18
19
20
21
22
23
24 public class HTMLRenderer extends AbstractIncrementingRenderer {
25
26 public static final String NAME = "html";
27
28 public static final StringProperty LINE_PREFIX = new StringProperty("linePrefix", "Prefix for line number anchor in the source file.", null, 1);
29 public static final StringProperty LINK_PREFIX = new StringProperty("linkPrefix", "Path to HTML source.", null, 0);
30
31 private String linkPrefix;
32 private String linePrefix;
33
34 private int violationCount = 1;
35 boolean colorize = true;
36
37 public HTMLRenderer() {
38 super(NAME, "HTML format");
39
40 definePropertyDescriptor(LINK_PREFIX);
41 definePropertyDescriptor(LINE_PREFIX);
42 }
43
44 public String defaultFileExtension() { return "html"; }
45
46
47
48
49
50
51
52
53 public void renderBody(Writer writer, Report report) throws IOException {
54 linkPrefix = getProperty(LINK_PREFIX);
55 linePrefix = getProperty(LINE_PREFIX);
56
57 writer.write("<center><h3>PMD report</h3></center>");
58 writer.write("<center><h3>Problems found</h3></center>");
59 writer.write("<table align=\"center\" cellspacing=\"0\" cellpadding=\"3\"><tr>" + PMD.EOL
60 + "<th>#</th><th>File</th><th>Line</th><th>Problem</th></tr>" + PMD.EOL);
61 setWriter(writer);
62 renderFileReport(report);
63 writer.write("</table>");
64 glomProcessingErrors(writer, errors);
65 if (showSuppressedViolations) {
66 glomSuppressions(writer, suppressed);
67 }
68 }
69
70
71
72
73 @Override
74 public void start() throws IOException {
75 Writer writer = getWriter();
76 writer.write("<html><head><title>PMD</title></head><body>" + PMD.EOL);
77 writer.write("<center><h3>PMD report</h3></center>");
78 writer.write("<center><h3>Problems found</h3></center>");
79 writer.write("<table align=\"center\" cellspacing=\"0\" cellpadding=\"3\"><tr>" + PMD.EOL
80 + "<th>#</th><th>File</th><th>Line</th><th>Problem</th></tr>" + PMD.EOL);
81 }
82
83
84
85
86 @Override
87 public void renderFileViolations(Iterator<RuleViolation> violations) throws IOException {
88 Writer writer = getWriter();
89 glomRuleViolations(writer, violations);
90 }
91
92
93
94
95 @Override
96 public void end() throws IOException {
97 Writer writer = getWriter();
98 writer.write("</table>");
99 glomProcessingErrors(writer, errors);
100 if (showSuppressedViolations) {
101 glomSuppressions(writer, suppressed);
102 }
103 writer.write("</body></html>" + PMD.EOL);
104 }
105
106 private void glomRuleViolations(Writer writer, Iterator<RuleViolation> violations) throws IOException {
107
108 StringBuilder buf = new StringBuilder(500);
109
110 while (violations.hasNext()) {
111 RuleViolation rv = violations.next();
112 buf.setLength(0);
113 buf.append("<tr");
114 if (colorize) {
115 buf.append(" bgcolor=\"lightgrey\"");
116 }
117 colorize = !colorize;
118 buf.append("> " + PMD.EOL);
119 buf.append("<td align=\"center\">" + violationCount + "</td>" + PMD.EOL);
120 buf.append("<td width=\"*%\">"
121 + maybeWrap(rv.getFilename(), linePrefix == null ? "" : linePrefix
122 + Integer.toString(rv.getBeginLine())) + "</td>" + PMD.EOL);
123 buf.append("<td align=\"center\" width=\"5%\">" + Integer.toString(rv.getBeginLine()) + "</td>" + PMD.EOL);
124
125 String d = StringUtil.htmlEncode(rv.getDescription());
126
127 String infoUrl = rv.getRule().getExternalInfoUrl();
128 if (StringUtil.isNotEmpty(infoUrl)) {
129 d = "<a href=\"" + infoUrl + "\">" + d + "</a>";
130 }
131 buf.append("<td width=\"*\">" + d + "</td>" + PMD.EOL);
132 buf.append("</tr>" + PMD.EOL);
133 writer.write(buf.toString());
134 violationCount++;
135 }
136 }
137
138 private void glomProcessingErrors(Writer writer, List<Report.ProcessingError> errors) throws IOException {
139
140 if (errors.isEmpty()) {
141 return;
142 }
143
144 writer.write("<hr/>");
145 writer.write("<center><h3>Processing errors</h3></center>");
146 writer.write("<table align=\"center\" cellspacing=\"0\" cellpadding=\"3\"><tr>" + PMD.EOL
147 + "<th>File</th><th>Problem</th></tr>" + PMD.EOL);
148
149 StringBuffer buf = new StringBuffer(500);
150 boolean colorize = true;
151 for (Report.ProcessingError pe : errors) {
152 buf.setLength(0);
153 buf.append("<tr");
154 if (colorize) {
155 buf.append(" bgcolor=\"lightgrey\"");
156 }
157 colorize = !colorize;
158 buf.append("> " + PMD.EOL);
159 buf.append("<td>" + pe.getFile() + "</td>" + PMD.EOL);
160 buf.append("<td>" + pe.getMsg() + "</td>" + PMD.EOL);
161 buf.append("</tr>" + PMD.EOL);
162 writer.write(buf.toString());
163 }
164 writer.write("</table>");
165 }
166
167 private void glomSuppressions(Writer writer, List<Report.SuppressedViolation> suppressed) throws IOException {
168 if (suppressed.isEmpty()) {
169 return;
170 }
171
172 writer.write("<hr/>");
173 writer.write("<center><h3>Suppressed warnings</h3></center>");
174 writer.write("<table align=\"center\" cellspacing=\"0\" cellpadding=\"3\"><tr>" + PMD.EOL
175 + "<th>File</th><th>Line</th><th>Rule</th><th>NOPMD or Annotation</th><th>Reason</th></tr>"
176 + PMD.EOL);
177
178 StringBuilder buf = new StringBuilder(500);
179 boolean colorize = true;
180 for (Report.SuppressedViolation sv : suppressed) {
181 buf.setLength(0);
182 buf.append("<tr");
183 if (colorize) {
184 buf.append(" bgcolor=\"lightgrey\"");
185 }
186 colorize = !colorize;
187 buf.append("> " + PMD.EOL);
188 buf.append("<td align=\"left\">" + sv.getRuleViolation().getFilename() + "</td>" + PMD.EOL);
189 buf.append("<td align=\"center\">" + sv.getRuleViolation().getBeginLine() + "</td>" + PMD.EOL);
190 buf.append("<td align=\"center\">" + sv.getRuleViolation().getRule().getName() + "</td>" + PMD.EOL);
191 buf.append("<td align=\"center\">" + (sv.suppressedByNOPMD() ? "NOPMD" : "Annotation") + "</td>"
192 + PMD.EOL);
193 buf.append("<td align=\"center\">" + (sv.getUserMessage() == null ? "" : sv.getUserMessage()) + "</td>"
194 + PMD.EOL);
195 buf.append("</tr>" + PMD.EOL);
196 writer.write(buf.toString());
197 }
198 writer.write("</table>");
199 }
200
201 private String maybeWrap(String filename, String line) {
202 if (StringUtil.isEmpty(linkPrefix)) {
203 return filename;
204 }
205 String newFileName = filename;
206 int index = filename.lastIndexOf('.');
207 if (index >= 0) {
208 newFileName = filename.substring(0, index).replace('\\', '/');
209 }
210 return "<a href=\"" + linkPrefix + newFileName + ".html#" + line + "\">" + newFileName + "</a>";
211 }
212 }