001 /**
002 * BSD-style license; for more info see http://pmd.sourceforge.net/license.html
003 */
004 package net.sourceforge.pmd.renderers;
005
006 import java.io.IOException;
007 import java.io.Writer;
008 import java.util.Iterator;
009 import java.util.List;
010 import java.util.Properties;
011
012 import net.sourceforge.pmd.PMD;
013 import net.sourceforge.pmd.Report;
014 import net.sourceforge.pmd.RuleViolation;
015 import net.sourceforge.pmd.util.StringUtil;
016
017 /**
018 * Renderer to basic HTML format.
019 */
020 public class HTMLRenderer extends AbstractIncrementingRenderer {
021
022 public static final String NAME = "html";
023
024 public static final String LINK_PREFIX = "linkPrefix";
025 public static final String LINE_PREFIX = "linePrefix";
026
027 private final String linkPrefix;
028 private final String linePrefix;
029
030 private int violationCount = 1;
031 boolean colorize = true;
032
033 public HTMLRenderer(Properties properties) {
034 super(NAME, "HTML format.", properties);
035
036 this.linkPrefix = properties.getProperty(LINK_PREFIX);
037 this.linePrefix = properties.getProperty(LINE_PREFIX);
038 }
039
040 /**
041 * Write the body of the main body of the HTML content.
042 *
043 * @param writer
044 * @param report
045 * @throws IOException
046 */
047 public void renderBody(Writer writer, Report report) throws IOException {
048 writer.write("<center><h3>PMD report</h3></center>");
049 writer.write("<center><h3>Problems found</h3></center>");
050 writer.write("<table align=\"center\" cellspacing=\"0\" cellpadding=\"3\"><tr>" + PMD.EOL
051 + "<th>#</th><th>File</th><th>Line</th><th>Problem</th></tr>" + PMD.EOL);
052 setWriter(writer);
053 renderFileReport(report);
054 writer.write("</table>");
055 glomProcessingErrors(writer, errors);
056 if (showSuppressedViolations) {
057 glomSuppressions(writer, suppressed);
058 }
059 }
060
061 /**
062 * {@inheritDoc}
063 */
064 @Override
065 public void start() throws IOException {
066 Writer writer = getWriter();
067 writer.write("<html><head><title>PMD</title></head><body>" + PMD.EOL);
068 writer.write("<center><h3>PMD report</h3></center>");
069 writer.write("<center><h3>Problems found</h3></center>");
070 writer.write("<table align=\"center\" cellspacing=\"0\" cellpadding=\"3\"><tr>" + PMD.EOL
071 + "<th>#</th><th>File</th><th>Line</th><th>Problem</th></tr>" + PMD.EOL);
072 }
073
074 /**
075 * {@inheritDoc}
076 */
077 @Override
078 public void renderFileViolations(Iterator<RuleViolation> violations) throws IOException {
079 Writer writer = getWriter();
080 glomRuleViolations(writer, violations);
081 }
082
083 /**
084 * {@inheritDoc}
085 */
086 @Override
087 public void end() throws IOException {
088 Writer writer = getWriter();
089 writer.write("</table>");
090 glomProcessingErrors(writer, errors);
091 if (showSuppressedViolations) {
092 glomSuppressions(writer, suppressed);
093 }
094 writer.write("</body></html>" + PMD.EOL);
095 }
096
097 private void glomRuleViolations(Writer writer, Iterator<RuleViolation> violations) throws IOException {
098 StringBuffer buf = new StringBuffer(500);
099 while (violations.hasNext()) {
100 RuleViolation rv = violations.next();
101 buf.setLength(0);
102 buf.append("<tr");
103 if (colorize) {
104 buf.append(" bgcolor=\"lightgrey\"");
105 }
106 colorize = !colorize;
107 buf.append("> " + PMD.EOL);
108 buf.append("<td align=\"center\">" + violationCount + "</td>" + PMD.EOL);
109 buf.append("<td width=\"*%\">"
110 + maybeWrap(rv.getFilename(), linePrefix == null ? "" : linePrefix
111 + Integer.toString(rv.getBeginLine())) + "</td>" + PMD.EOL);
112 buf.append("<td align=\"center\" width=\"5%\">" + Integer.toString(rv.getBeginLine()) + "</td>" + PMD.EOL);
113
114 String d = StringUtil.htmlEncode(rv.getDescription());
115
116 if (rv.getRule().getExternalInfoUrl() != null && rv.getRule().getExternalInfoUrl().length() != 0) {
117 d = "<a href=\"" + rv.getRule().getExternalInfoUrl() + "\">" + d + "</a>";
118 }
119 buf.append("<td width=\"*\">" + d + "</td>" + PMD.EOL);
120 buf.append("</tr>" + PMD.EOL);
121 writer.write(buf.toString());
122 violationCount++;
123 }
124 }
125
126 private void glomProcessingErrors(Writer writer, List<Report.ProcessingError> errors) throws IOException {
127 if (!errors.isEmpty()) {
128 writer.write("<hr/>");
129 writer.write("<center><h3>Processing errors</h3></center>");
130 writer.write("<table align=\"center\" cellspacing=\"0\" cellpadding=\"3\"><tr>" + PMD.EOL
131 + "<th>File</th><th>Problem</th></tr>" + PMD.EOL);
132
133 StringBuffer buf = new StringBuffer(500);
134 boolean colorize = true;
135 for (Report.ProcessingError pe : errors) {
136 buf.setLength(0);
137 buf.append("<tr");
138 if (colorize) {
139 buf.append(" bgcolor=\"lightgrey\"");
140 }
141 colorize = !colorize;
142 buf.append("> " + PMD.EOL);
143 buf.append("<td>" + pe.getFile() + "</td>" + PMD.EOL);
144 buf.append("<td>" + pe.getMsg() + "</td>" + PMD.EOL);
145 buf.append("</tr>" + PMD.EOL);
146 writer.write(buf.toString());
147
148 }
149 writer.write("</table>");
150 }
151 }
152
153 private void glomSuppressions(Writer writer, List<Report.SuppressedViolation> suppressed) throws IOException {
154 if (!suppressed.isEmpty()) {
155 writer.write("<hr/>");
156 writer.write("<center><h3>Suppressed warnings</h3></center>");
157 writer.write("<table align=\"center\" cellspacing=\"0\" cellpadding=\"3\"><tr>" + PMD.EOL
158 + "<th>File</th><th>Line</th><th>Rule</th><th>NOPMD or Annotation</th><th>Reason</th></tr>"
159 + PMD.EOL);
160
161 StringBuffer buf = new StringBuffer(500);
162 boolean colorize = true;
163 for (Report.SuppressedViolation sv : suppressed) {
164 buf.setLength(0);
165 buf.append("<tr");
166 if (colorize) {
167 buf.append(" bgcolor=\"lightgrey\"");
168 }
169 colorize = !colorize;
170 buf.append("> " + PMD.EOL);
171 buf.append("<td align=\"left\">" + sv.getRuleViolation().getFilename() + "</td>" + PMD.EOL);
172 buf.append("<td align=\"center\">" + sv.getRuleViolation().getBeginLine() + "</td>" + PMD.EOL);
173 buf.append("<td align=\"center\">" + sv.getRuleViolation().getRule().getName() + "</td>" + PMD.EOL);
174 buf.append("<td align=\"center\">" + (sv.suppressedByNOPMD() ? "NOPMD" : "Annotation") + "</td>"
175 + PMD.EOL);
176 buf.append("<td align=\"center\">" + (sv.getUserMessage() == null ? "" : sv.getUserMessage()) + "</td>"
177 + PMD.EOL);
178 buf.append("</tr>" + PMD.EOL);
179 writer.write(buf.toString());
180 }
181 writer.write("</table>");
182 }
183 }
184
185 private String maybeWrap(String filename, String line) {
186 if (linkPrefix == null) {
187 return filename;
188 }
189 String newFileName = filename;
190 int index = filename.lastIndexOf('.');
191 if (index >= 0) {
192 newFileName = filename.substring(0, index).replace('\\', '/');
193 }
194 return "<a href=\"" + linkPrefix + newFileName + ".html#" + line + "\">" + newFileName + "</a>";
195 }
196 }
|