001: /**
002: * BSD-style license; for more info see http://pmd.sourceforge.net/license.html
003: */package net.sourceforge.pmd.renderers;
004:
005: import net.sourceforge.pmd.IRuleViolation;
006: import net.sourceforge.pmd.PMD;
007: import net.sourceforge.pmd.Report;
008: import net.sourceforge.pmd.util.StringUtil;
009:
010: import java.io.IOException;
011: import java.io.Writer;
012: import java.text.SimpleDateFormat;
013: import java.util.Date;
014: import java.util.Iterator;
015:
016: public class XMLRenderer extends OnTheFlyRenderer {
017:
018: // FIXME - hardcoded character encoding, booooooo
019: protected String encoding = "UTF-8";
020:
021: public void start() throws IOException {
022: Writer writer = getWriter();
023: StringBuffer buf = new StringBuffer();
024: buf.append(
025: "<?xml version=\"1.0\" encoding=\"" + this .encoding
026: + "\"?>").append(PMD.EOL);
027: createVersionAttr(buf);
028: createTimestampAttr(buf);
029: // FIXME: elapsed time not available until the end of the processing
030: //buf.append(createTimeElapsedAttr(report));
031: buf.append('>').append(PMD.EOL);
032: writer.write(buf.toString());
033: }
034:
035: public void renderFileViolations(Iterator<IRuleViolation> violations)
036: throws IOException {
037: Writer writer = getWriter();
038: StringBuffer buf = new StringBuffer();
039: String filename = null;
040:
041: // rule violations
042: while (violations.hasNext()) {
043: buf.setLength(0);
044: IRuleViolation rv = violations.next();
045: if (!rv.getFilename().equals(filename)) { // New File
046: if (filename != null) {// Not first file ?
047: buf.append("</file>").append(PMD.EOL);
048: }
049: filename = rv.getFilename();
050: buf.append("<file name=\"");
051: StringUtil.appendXmlEscaped(buf, filename);
052: buf.append("\">").append(PMD.EOL);
053: }
054:
055: buf.append("<violation beginline=\"").append(
056: rv.getBeginLine());
057: buf.append("\" endline=\"").append(rv.getEndLine());
058: buf.append("\" begincolumn=\"").append(rv.getBeginColumn());
059: buf.append("\" endcolumn=\"").append(rv.getEndColumn());
060: buf.append("\" rule=\"");
061: StringUtil.appendXmlEscaped(buf, rv.getRule().getName());
062: buf.append("\" ruleset=\"");
063: StringUtil.appendXmlEscaped(buf, rv.getRule()
064: .getRuleSetName());
065: buf.append('"');
066: maybeAdd("package", rv.getPackageName(), buf);
067: maybeAdd("class", rv.getClassName(), buf);
068: maybeAdd("method", rv.getMethodName(), buf);
069: maybeAdd("variable", rv.getVariableName(), buf);
070: maybeAdd("externalInfoUrl", rv.getRule()
071: .getExternalInfoUrl(), buf);
072: buf.append(" priority=\"");
073: buf.append(rv.getRule().getPriority());
074: buf.append("\">").append(PMD.EOL);
075: StringUtil.appendXmlEscaped(buf, rv.getDescription());
076:
077: buf.append(PMD.EOL);
078: buf.append("</violation>");
079: buf.append(PMD.EOL);
080: writer.write(buf.toString());
081: }
082: if (filename != null) { // Not first file ?
083: writer.write("</file>");
084: writer.write(PMD.EOL);
085: }
086: }
087:
088: public void end() throws IOException {
089: Writer writer = getWriter();
090: StringBuffer buf = new StringBuffer();
091: // errors
092: for (Report.ProcessingError pe : errors) {
093: buf.setLength(0);
094: buf.append("<error ").append("filename=\"");
095: StringUtil.appendXmlEscaped(buf, pe.getFile());
096: buf.append("\" msg=\"");
097: StringUtil.appendXmlEscaped(buf, pe.getMsg());
098: buf.append("\"/>").append(PMD.EOL);
099: writer.write(buf.toString());
100: }
101:
102: // suppressed violations
103: if (showSuppressedViolations) {
104: for (Report.SuppressedViolation s : suppressed) {
105: buf.setLength(0);
106: buf.append("<suppressedviolation ").append(
107: "filename=\"");
108: StringUtil.appendXmlEscaped(buf, s.getRuleViolation()
109: .getFilename());
110: buf.append("\" suppressiontype=\"");
111: StringUtil.appendXmlEscaped(buf,
112: s.suppressedByNOPMD() ? "nopmd" : "annotation");
113: buf.append("\" msg=\"");
114: StringUtil.appendXmlEscaped(buf, s.getRuleViolation()
115: .getDescription());
116: buf.append("\" usermsg=\"");
117: StringUtil.appendXmlEscaped(buf,
118: (s.getUserMessage() == null ? "" : s
119: .getUserMessage()));
120: buf.append("\"/>").append(PMD.EOL);
121: writer.write(buf.toString());
122: }
123: }
124:
125: writer.write("</pmd>");
126: }
127:
128: private void maybeAdd(String attr, String value, StringBuffer buf) {
129: if (value != null && value.length() > 0) {
130: buf.append(' ').append(attr).append("=\"");
131: StringUtil.appendXmlEscaped(buf, value);
132: buf.append('"');
133: }
134: }
135:
136: private void createVersionAttr(StringBuffer buffer) {
137: buffer.append("<pmd version=\"").append(PMD.VERSION)
138: .append('"');
139: }
140:
141: private void createTimestampAttr(StringBuffer buffer) {
142: buffer.append(" timestamp=\"").append(
143: new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss.SSS")
144: .format(new Date())).append('"');
145: }
146:
147: private String createTimeElapsedAttr(Report rpt) {
148: Report.ReadableDuration d = new Report.ReadableDuration(rpt
149: .getElapsedTimeInMillis());
150: return " elapsedTime=\"" + d.getTime() + "\"";
151: }
152:
153: }
|