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.text.SimpleDateFormat;
14 import java.util.Date;
15 import java.util.Iterator;
16
17 public class XMLRenderer extends OnTheFlyRenderer {
18
19
20 protected String encoding = "UTF-8";
21
22 public void start() throws IOException {
23 Writer writer = getWriter();
24 StringBuffer buf = new StringBuffer();
25 buf.append("<?xml version=\"1.0\" encoding=\"" + this.encoding + "\"?>").append(PMD.EOL);
26 createVersionAttr(buf);
27 createTimestampAttr(buf);
28
29
30 buf.append('>').append(PMD.EOL);
31 writer.write(buf.toString());
32 }
33
34 public void renderFileViolations(Iterator<IRuleViolation> violations) throws IOException {
35 Writer writer = getWriter();
36 StringBuffer buf = new StringBuffer();
37 String filename = null;
38
39
40 while (violations.hasNext()) {
41 buf.setLength(0);
42 IRuleViolation rv = violations.next();
43 if (!rv.getFilename().equals(filename)) {
44 if (filename != null) {
45 buf.append("</file>").append(PMD.EOL);
46 }
47 filename = rv.getFilename();
48 buf.append("<file name=\"");
49 StringUtil.appendXmlEscaped(buf, filename);
50 buf.append("\">").append(PMD.EOL);
51 }
52
53 buf.append("<violation beginline=\"").append(rv.getBeginLine());
54 buf.append("\" endline=\"").append(rv.getEndLine());
55 buf.append("\" begincolumn=\"").append(rv.getBeginColumn());
56 buf.append("\" endcolumn=\"").append(rv.getEndColumn());
57 buf.append("\" rule=\"");
58 StringUtil.appendXmlEscaped(buf, rv.getRule().getName());
59 buf.append("\" ruleset=\"");
60 StringUtil.appendXmlEscaped(buf, rv.getRule().getRuleSetName());
61 buf.append('"');
62 maybeAdd("package", rv.getPackageName(), buf);
63 maybeAdd("class", rv.getClassName(), buf);
64 maybeAdd("method", rv.getMethodName(), buf);
65 maybeAdd("variable", rv.getVariableName(), buf);
66 maybeAdd("externalInfoUrl", rv.getRule().getExternalInfoUrl(), buf);
67 buf.append(" priority=\"");
68 buf.append(rv.getRule().getPriority());
69 buf.append("\">").append(PMD.EOL);
70 StringUtil.appendXmlEscaped(buf, rv.getDescription());
71
72 buf.append(PMD.EOL);
73 buf.append("</violation>");
74 buf.append(PMD.EOL);
75 writer.write(buf.toString());
76 }
77 if (filename != null) {
78 writer.write("</file>");
79 writer.write(PMD.EOL);
80 }
81 }
82
83 public void end() throws IOException {
84 Writer writer = getWriter();
85 StringBuffer buf = new StringBuffer();
86
87 for (Report.ProcessingError pe: errors) {
88 buf.setLength(0);
89 buf.append("<error ").append("filename=\"");
90 StringUtil.appendXmlEscaped(buf, pe.getFile());
91 buf.append("\" msg=\"");
92 StringUtil.appendXmlEscaped(buf, pe.getMsg());
93 buf.append("\"/>").append(PMD.EOL);
94 writer.write(buf.toString());
95 }
96
97
98 if (showSuppressedViolations) {
99 for (Report.SuppressedViolation s: suppressed) {
100 buf.setLength(0);
101 buf.append("<suppressedviolation ").append("filename=\"");
102 StringUtil.appendXmlEscaped(buf, s.getRuleViolation().getFilename());
103 buf.append("\" suppressiontype=\"");
104 StringUtil.appendXmlEscaped(buf, s.suppressedByNOPMD() ? "nopmd" : "annotation");
105 buf.append("\" msg=\"");
106 StringUtil.appendXmlEscaped(buf, s.getRuleViolation().getDescription());
107 buf.append("\" usermsg=\"");
108 StringUtil.appendXmlEscaped(buf, (s.getUserMessage() == null ? "" : s.getUserMessage()));
109 buf.append("\"/>").append(PMD.EOL);
110 writer.write(buf.toString());
111 }
112 }
113
114 writer.write("</pmd>");
115 }
116
117 private void maybeAdd(String attr, String value, StringBuffer buf) {
118 if (value != null && value.length() > 0) {
119 buf.append(' ').append(attr).append("=\"");
120 StringUtil.appendXmlEscaped(buf, value);
121 buf.append('"');
122 }
123 }
124
125 private void createVersionAttr(StringBuffer buffer) {
126 buffer.append("<pmd version=\"").append(PMD.VERSION).append('"');
127 }
128
129 private void createTimestampAttr(StringBuffer buffer) {
130 buffer.append(" timestamp=\"").append(new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss.SSS").format(new Date())).append('"');
131 }
132
133 private String createTimeElapsedAttr(Report rpt) {
134 Report.ReadableDuration d = new Report.ReadableDuration(rpt.getElapsedTimeInMillis());
135 return " elapsedTime=\"" + d.getTime() + "\"";
136 }
137
138 }