1 /***
2 * BSD-style license; for more info see http://pmd.sourceforge.net/license.html
3 */
4 package net.sourceforge.pmd.renderers;
5
6 import net.sourceforge.pmd.IRuleViolation;
7 import net.sourceforge.pmd.PMD;
8 import net.sourceforge.pmd.Report;
9 import net.sourceforge.pmd.util.StringUtil;
10
11 import java.io.IOException;
12 import java.io.Writer;
13 import java.util.Iterator;
14
15 public class HTMLRenderer extends AbstractRenderer {
16
17 private String linkPrefix;
18 private String linePrefix;
19
20 public HTMLRenderer(String linkPrefix, String linePrefix) {
21 this.linkPrefix = linkPrefix;
22 this.linePrefix = linePrefix;
23
24 }
25
26 public HTMLRenderer() {
27 this(null, null);
28 }
29
30 public void render(Writer writer, Report report) throws IOException {
31 writer.write("<html><head><title>PMD</title></head><body>" + PMD.EOL);
32 renderBody(writer, report);
33 writer.write("</body></html>");
34 }
35
36 public void renderBody(Writer writer, Report report) throws IOException {
37 glomIRuleViolations(writer, report);
38 glomProcessingErrors(writer, report);
39 if (showSuppressedViolations) {
40 glomSuppressions(writer, report);
41 }
42 }
43
44 private void glomIRuleViolations(Writer writer, Report report) throws IOException {
45 boolean colorize = true;
46 int violationCount = 1;
47 StringBuffer buf = new StringBuffer(500);
48 writer.write("<center><h3>PMD report</h3></center>");
49 writer.write("<center><h3>Problems found</h3></center>");
50 writer.write("<table align=\"center\" cellspacing=\"0\" cellpadding=\"3\"><tr>" + PMD.EOL + "<th>#</th><th>File</th><th>Line</th><th>Problem</th></tr>" + PMD.EOL);
51 for (Iterator i = report.iterator(); i.hasNext();) {
52 IRuleViolation rv = (IRuleViolation) i.next();
53 buf.setLength(0);
54 buf.append("<tr");
55 if (colorize) {
56 buf.append(" bgcolor=\"lightgrey\"");
57 }
58 colorize = !colorize;
59 buf.append("> " + PMD.EOL);
60 buf.append("<td align=\"center\">" + violationCount + "</td>" + PMD.EOL);
61 buf.append("<td width=\"*%\">" + maybeWrap(rv.getFilename(),linePrefix==null?"":linePrefix + Integer.toString(rv.getBeginLine())) + "</td>" + PMD.EOL);
62 buf.append("<td align=\"center\" width=\"5%\">" + Integer.toString(rv.getBeginLine()) + "</td>" + PMD.EOL);
63
64 String d = StringUtil.htmlEncode(rv.getDescription());
65
66 if (rv.getRule().getExternalInfoUrl() != null && rv.getRule().getExternalInfoUrl().length() != 0) {
67 d = "<a href=\"" + rv.getRule().getExternalInfoUrl() + "\">" + d + "</a>";
68 }
69 buf.append("<td width=\"*\">" + d + "</td>" + PMD.EOL);
70 buf.append("</tr>" + PMD.EOL);
71 writer.write(buf.toString());
72 violationCount++;
73 }
74 if (violationCount > 0) {
75 writer.write("</table>");
76 }
77 }
78
79 private void glomProcessingErrors(Writer writer, Report report) throws IOException {
80 boolean colorize = true;
81 int violationCount;
82
83 if (report.errors().hasNext()) {
84 writer.write("<hr/>");
85 writer.write("<center><h3>Processing errors</h3></center>");
86 writer.write("<table align=\"center\" cellspacing=\"0\" cellpadding=\"3\"><tr>" + PMD.EOL + "<th>File</th><th>Problem</th></tr>" + PMD.EOL);
87 }
88 violationCount = 0;
89 StringBuffer buf = new StringBuffer(500);
90 for (Iterator i = report.errors(); i.hasNext();) {
91 Report.ProcessingError pe = (Report.ProcessingError) i.next();
92 buf.setLength(0);
93 buf.append("<tr");
94 if (colorize) {
95 buf.append(" bgcolor=\"lightgrey\"");
96 }
97 colorize = !colorize;
98 buf.append("> " + PMD.EOL);
99 buf.append("<td>" + pe.getFile() + "</td>" + PMD.EOL);
100 buf.append("<td>" + pe.getMsg() + "</td>" + PMD.EOL);
101 buf.append("</tr>" + PMD.EOL);
102 writer.write(buf.toString());
103 violationCount++;
104 }
105 if (violationCount > 0) {
106 writer.write("</table>");
107 }
108 }
109
110 private void glomSuppressions(Writer writer, Report report) throws IOException {
111 boolean colorize = true;
112 boolean hasSuppressedViolations = !report.getSuppressedRuleViolations().isEmpty();
113 if (hasSuppressedViolations) {
114 writer.write("<hr/>");
115 writer.write("<center><h3>Suppressed warnings</h3></center>");
116 writer.write("<table align=\"center\" cellspacing=\"0\" cellpadding=\"3\"><tr>" + PMD.EOL + "<th>File</th><th>Line</th><th>Rule</th><th>NOPMD or Annotation</th><th>Reason</th></tr>" + PMD.EOL);
117 }
118 Report.SuppressedViolation sv;
119 StringBuffer buf = new StringBuffer(500);
120 for (Iterator i = report.getSuppressedRuleViolations().iterator(); i.hasNext();) {
121 sv = (Report.SuppressedViolation) i.next();
122 buf.setLength(0);
123 buf.append("<tr");
124 if (colorize) {
125 buf.append(" bgcolor=\"lightgrey\"");
126 }
127 colorize = !colorize;
128 buf.append("> " + PMD.EOL);
129 buf.append("<td align=\"left\">" + sv.getRuleViolation().getFilename() + "</td>" + PMD.EOL);
130 buf.append("<td align=\"center\">" + sv.getRuleViolation().getBeginLine() + "</td>" + PMD.EOL);
131 buf.append("<td align=\"center\">" + sv.getRuleViolation().getRule().getName() + "</td>" + PMD.EOL);
132 buf.append("<td align=\"center\">" + (sv.suppressedByNOPMD() ? "NOPMD" : "Annotation") + "</td>" + PMD.EOL);
133 buf.append("<td align=\"center\">" + (sv.getUserMessage() == null ? "" : sv.getUserMessage()) + "</td>" + PMD.EOL);
134 buf.append("</tr>" + PMD.EOL);
135 writer.write(buf.toString());
136 }
137 if (hasSuppressedViolations) {
138 writer.write("</table>");
139 }
140 }
141
142 private String maybeWrap(String filename, String line) {
143 if (linkPrefix == null) {
144 return filename;
145 }
146 String newFileName = filename.substring(0, filename.lastIndexOf('.')).replace('//', '/');
147 return "<a href=\"" + linkPrefix + newFileName + ".html#" + line + "\">" + newFileName + "</a>";
148 }
149 }