1
2
3
4 package net.sourceforge.pmd.renderers;
5
6 import java.io.IOException;
7 import java.io.Writer;
8 import java.text.SimpleDateFormat;
9 import java.util.Date;
10 import java.util.Iterator;
11
12 import net.sourceforge.pmd.PMD;
13 import net.sourceforge.pmd.Report;
14 import net.sourceforge.pmd.RuleViolation;
15 import net.sourceforge.pmd.lang.rule.properties.StringProperty;
16 import net.sourceforge.pmd.util.StringUtil;
17
18
19
20
21 public class XMLRenderer extends AbstractIncrementingRenderer {
22
23 public static final String NAME = "xml";
24
25 public static final StringProperty ENCODING = new StringProperty("encoding",
26 "XML encoding format, defaults to UTF-8.", "UTF-8", 0);
27 private boolean useUTF8 = false;
28
29
30 public XMLRenderer() {
31 super(NAME, "XML format.");
32 definePropertyDescriptor(ENCODING);
33 }
34
35 public XMLRenderer(String encoding) {
36 this();
37 setProperty(ENCODING, encoding);
38 }
39
40 public String defaultFileExtension() {
41 return "xml";
42 }
43
44
45
46
47 @Override
48 public void start() throws IOException {
49 String encoding = getProperty(ENCODING);
50 if (encoding.equalsIgnoreCase("utf-8")) {
51 useUTF8 = true;
52 }
53
54 Writer writer = getWriter();
55 StringBuilder buf = new StringBuilder(500);
56 buf.append("<?xml version=\"1.0\" encoding=\"" + encoding + "\"?>").append(PMD.EOL);
57 createVersionAttr(buf);
58 createTimestampAttr(buf);
59
60
61 buf.append('>').append(PMD.EOL);
62 writer.write(buf.toString());
63 }
64
65
66
67
68 @Override
69 public void renderFileViolations(Iterator<RuleViolation> violations) throws IOException {
70 Writer writer = getWriter();
71 StringBuilder buf = new StringBuilder(500);
72 String filename = null;
73
74
75 while (violations.hasNext()) {
76 buf.setLength(0);
77 RuleViolation rv = violations.next();
78 if (!rv.getFilename().equals(filename)) {
79 if (filename != null) {
80 buf.append("</file>").append(PMD.EOL);
81 }
82 filename = rv.getFilename();
83 buf.append("<file name=\"");
84 StringUtil.appendXmlEscaped(buf, filename, useUTF8);
85 buf.append("\">").append(PMD.EOL);
86 }
87
88 buf.append("<violation beginline=\"").append(rv.getBeginLine());
89 buf.append("\" endline=\"").append(rv.getEndLine());
90 buf.append("\" begincolumn=\"").append(rv.getBeginColumn());
91 buf.append("\" endcolumn=\"").append(rv.getEndColumn());
92 buf.append("\" rule=\"");
93 StringUtil.appendXmlEscaped(buf, rv.getRule().getName(), useUTF8);
94 buf.append("\" ruleset=\"");
95 StringUtil.appendXmlEscaped(buf, rv.getRule().getRuleSetName(), useUTF8);
96 buf.append('"');
97 maybeAdd("package", rv.getPackageName(), buf);
98 maybeAdd("class", rv.getClassName(), buf);
99 maybeAdd("method", rv.getMethodName(), buf);
100 maybeAdd("variable", rv.getVariableName(), buf);
101 maybeAdd("externalInfoUrl", rv.getRule().getExternalInfoUrl(), buf);
102 buf.append(" priority=\"");
103 buf.append(rv.getRule().getPriority().getPriority());
104 buf.append("\">").append(PMD.EOL);
105 StringUtil.appendXmlEscaped(buf, rv.getDescription(), useUTF8);
106
107 buf.append(PMD.EOL);
108 buf.append("</violation>");
109 buf.append(PMD.EOL);
110 writer.write(buf.toString());
111 }
112 if (filename != null) {
113 writer.write("</file>");
114 writer.write(PMD.EOL);
115 }
116 }
117
118
119
120
121 @Override
122 public void end() throws IOException {
123 Writer writer = getWriter();
124 StringBuilder buf = new StringBuilder(500);
125
126 for (Report.ProcessingError pe : errors) {
127 buf.setLength(0);
128 buf.append("<error ").append("filename=\"");
129 StringUtil.appendXmlEscaped(buf, pe.getFile(), useUTF8);
130 buf.append("\" msg=\"");
131 StringUtil.appendXmlEscaped(buf, pe.getMsg(), useUTF8);
132 buf.append("\"/>").append(PMD.EOL);
133 writer.write(buf.toString());
134 }
135
136
137 if (showSuppressedViolations) {
138 for (Report.SuppressedViolation s : suppressed) {
139 buf.setLength(0);
140 buf.append("<suppressedviolation ").append("filename=\"");
141 StringUtil.appendXmlEscaped(buf, s.getRuleViolation().getFilename(), useUTF8);
142 buf.append("\" suppressiontype=\"");
143 StringUtil.appendXmlEscaped(buf, s.suppressedByNOPMD() ? "nopmd" : "annotation", useUTF8);
144 buf.append("\" msg=\"");
145 StringUtil.appendXmlEscaped(buf, s.getRuleViolation().getDescription(), useUTF8);
146 buf.append("\" usermsg=\"");
147 StringUtil.appendXmlEscaped(buf, s.getUserMessage() == null ? "" : s.getUserMessage(), useUTF8);
148 buf.append("\"/>").append(PMD.EOL);
149 writer.write(buf.toString());
150 }
151 }
152
153 writer.write("</pmd>" + PMD.EOL);
154 }
155
156 private void maybeAdd(String attr, String value, StringBuilder buf) {
157 if (value != null && value.length() > 0) {
158 buf.append(' ').append(attr).append("=\"");
159 StringUtil.appendXmlEscaped(buf, value, useUTF8);
160 buf.append('"');
161 }
162 }
163
164 private void createVersionAttr(StringBuilder buffer) {
165 buffer.append("<pmd version=\"").append(PMD.VERSION).append('"');
166 }
167
168 private void createTimestampAttr(StringBuilder buffer) {
169 buffer.append(" timestamp=\"").append(new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss.SSS").format(new Date()))
170 .append('"');
171 }
172
173
174
175
176
177
178
179
180 }