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.PMD;
7 import net.sourceforge.pmd.Report;
8 import net.sourceforge.pmd.IRuleViolation;
9 import net.sourceforge.pmd.util.StringUtil;
10
11 import java.text.SimpleDateFormat;
12 import java.util.Date;
13 import java.util.Iterator;
14
15 public class XMLRenderer extends AbstractRenderer implements Renderer {
16
17 public String render(Report report) {
18
19 StringBuffer buf = new StringBuffer("<?xml version=\"1.0\" encoding=\"UTF-8\"?>" + PMD.EOL + createVersionAttr() + createTimestampAttr() + createTimeElapsedAttr(report) + ">" + PMD.EOL);
20 String filename = null;
21
22
23 for (Iterator i = report.iterator(); i.hasNext();) {
24 IRuleViolation rv = (IRuleViolation) i.next();
25 if (!rv.getFilename().equals(filename)) {
26 if (filename != null) {
27 buf.append("</file>" + PMD.EOL);
28 }
29 filename = rv.getFilename();
30 buf.append("<file name=\"");
31 StringUtil.appendXmlEscaped(buf, filename);
32 buf.append("\">").append(PMD.EOL);
33 }
34
35 buf.append("<violation line=\"").append(rv.getBeginLine()).append("\"");
36 buf.append(" rule=\"");
37 StringUtil.appendXmlEscaped(buf, rv.getRule().getName());
38 buf.append("\"");
39 buf.append(" ruleset=\"");
40 StringUtil.appendXmlEscaped(buf, rv.getRule().getRuleSetName());
41 buf.append("\"");
42 maybeAdd("package", rv.getPackageName(), buf);
43 maybeAdd("class", rv.getClassName(), buf);
44 maybeAdd("method", rv.getMethodName(), buf);
45 maybeAdd("externalInfoUrl", rv.getRule().getExternalInfoUrl(), buf);
46 buf.append(" priority=\"");
47 buf.append(rv.getRule().getPriority());
48 buf.append("\">");
49 buf.append(PMD.EOL);
50 StringUtil.appendXmlEscaped(buf, rv.getDescription());
51
52 buf.append(PMD.EOL);
53 buf.append("</violation>");
54 buf.append(PMD.EOL);
55 }
56 if (filename != null) {
57 buf.append("</file>" + PMD.EOL);
58 }
59
60
61 for (Iterator i = report.errors(); i.hasNext();) {
62 Report.ProcessingError pe = (Report.ProcessingError) i.next();
63 buf.append("<error ").append("filename=\"");
64 StringUtil.appendXmlEscaped(buf, pe.getFile());
65 buf.append("\" msg=\"");
66 StringUtil.appendXmlEscaped(buf, pe.getMsg());
67 buf.append("\"/>").append(PMD.EOL);
68 }
69
70
71 if (showSuppressedViolations) {
72 for (Iterator i = report.getSuppressedRuleViolations().iterator(); i.hasNext();) {
73 Report.SuppressedViolation suppressed = (Report.SuppressedViolation) i.next();
74 buf.append("<suppressedviolation ").append("filename=\"");
75 StringUtil.appendXmlEscaped(buf, suppressed.getRuleViolation().getFilename());
76 buf.append("\" suppressiontype=\"");
77 StringUtil.appendXmlEscaped(buf, suppressed.suppressedByNOPMD() ? "nopmd" : "annotation");
78 buf.append("\" msg=\"");
79 StringUtil.appendXmlEscaped(buf, suppressed.getRuleViolation().getDescription());
80 buf.append("\"/>").append(PMD.EOL);
81 }
82 }
83
84 buf.append("</pmd>");
85 return buf.toString();
86 }
87
88 private void maybeAdd(String attr, String value, StringBuffer buf) {
89 if (value != null && value.length() > 0) {
90 buf.append(" " + attr + "=\"");
91 StringUtil.appendXmlEscaped(buf, value);
92 buf.append("\"");
93 }
94 }
95
96 private String createVersionAttr() {
97 return "<pmd version=\"" + PMD.VERSION + "\"";
98 }
99
100 private String createTimestampAttr() {
101 return " timestamp=\"" + new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss.SSS").format(new Date()) + "\"";
102 }
103
104 private String createTimeElapsedAttr(Report rpt) {
105 Report.ReadableDuration d = new Report.ReadableDuration(rpt.getElapsedTimeInMillis());
106 return " elapsedTime=\"" + d.getTime() + "\"";
107 }
108
109 }