View Javadoc

    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 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   * Renderer to XML format.
    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", "XML encoding format, defaults to UTF-8.", "UTF-8", 0);
    26
    27      public XMLRenderer() {
    28  		super(NAME, "XML format.");
    29  		definePropertyDescriptor(ENCODING);
    30      }
    31
    32      public XMLRenderer(String encoding) {
    33  	this();
    34  	setProperty(ENCODING, encoding);
    35      }
    36
    37      public String defaultFileExtension() { return "xml"; }
    38
    39      /**
    40       * {@inheritDoc}
    41       */
    42      @Override
    43      public void start() throws IOException {
    44  		String encoding = getProperty(ENCODING);
    45
    46  		Writer writer = getWriter();
    47  		StringBuilder buf = new StringBuilder(500);
    48  		buf.append("<?xml version=\"1.0\" encoding=\"" + encoding + "\"?>").append(PMD.EOL);
    49  		createVersionAttr(buf);
    50  		createTimestampAttr(buf);
    51  		// FIXME: elapsed time not available until the end of the processing
    52  		//buf.append(createTimeElapsedAttr(report));
    53  		buf.append('>').append(PMD.EOL);
    54  		writer.write(buf.toString());
    55      }
    56
    57      /**
    58       * {@inheritDoc}
    59       */
    60      @Override
    61      public void renderFileViolations(Iterator<RuleViolation> violations) throws IOException {
    62  		Writer writer = getWriter();
    63  		StringBuilder buf = new StringBuilder(500);
    64  		String filename = null;
    65
    66  		// rule violations
    67  		while (violations.hasNext()) {
    68  		    buf.setLength(0);
    69  		    RuleViolation rv = violations.next();
    70  		    if (!rv.getFilename().equals(filename)) { // New File
    71  			if (filename != null) {// Not first file ?
    72  			    buf.append("</file>").append(PMD.EOL);
    73  			}
    74  			filename = rv.getFilename();
    75  			buf.append("<file name=\"");
    76  			StringUtil.appendXmlEscaped(buf, filename);
    77  			buf.append("\">").append(PMD.EOL);
    78  		    }
    79
    80  		    buf.append("<violation beginline=\"").append(rv.getBeginLine());
    81  		    buf.append("\" endline=\"").append(rv.getEndLine());
    82  		    buf.append("\" begincolumn=\"").append(rv.getBeginColumn());
    83  		    buf.append("\" endcolumn=\"").append(rv.getEndColumn());
    84  		    buf.append("\" rule=\"");
    85  		    StringUtil.appendXmlEscaped(buf, rv.getRule().getName());
    86  		    buf.append("\" ruleset=\"");
    87  		    StringUtil.appendXmlEscaped(buf, rv.getRule().getRuleSetName());
    88  		    buf.append('"');
    89  		    maybeAdd("package", rv.getPackageName(), buf);
    90  		    maybeAdd("class", rv.getClassName(), buf);
    91  		    maybeAdd("method", rv.getMethodName(), buf);
    92  		    maybeAdd("variable", rv.getVariableName(), buf);
    93  		    maybeAdd("externalInfoUrl", rv.getRule().getExternalInfoUrl(), buf);
    94  		    buf.append(" priority=\"");
    95  		    buf.append(rv.getRule().getPriority().getPriority());
    96  		    buf.append("\">").append(PMD.EOL);
    97  		    StringUtil.appendXmlEscaped(buf, rv.getDescription());
    98
    99  		    buf.append(PMD.EOL);
    100 		    buf.append("</violation>");
    101 		    buf.append(PMD.EOL);
    102 		    writer.write(buf.toString());
    103 		}
    104 		if (filename != null) { // Not first file ?
    105 		    writer.write("</file>");
    106 		    writer.write(PMD.EOL);
    107 		}
    108     }
    109
    110     /**
    111      * {@inheritDoc}
    112      */
    113     @Override
    114     public void end() throws IOException {
    115 		Writer writer = getWriter();
    116 		StringBuilder buf = new StringBuilder(500);
    117 		// errors
    118 		for (Report.ProcessingError pe : errors) {
    119 		    buf.setLength(0);
    120 		    buf.append("<error ").append("filename=\"");
    121 		    StringUtil.appendXmlEscaped(buf, pe.getFile());
    122 		    buf.append("\" msg=\"");
    123 		    StringUtil.appendXmlEscaped(buf, pe.getMsg());
    124 		    buf.append("\"/>").append(PMD.EOL);
    125 		    writer.write(buf.toString());
    126 		}
    127
    128 		// suppressed violations
    129 		if (showSuppressedViolations) {
    130 		    for (Report.SuppressedViolation s : suppressed) {
    131 			buf.setLength(0);
    132 			buf.append("<suppressedviolation ").append("filename=\"");
    133 			StringUtil.appendXmlEscaped(buf, s.getRuleViolation().getFilename());
    134 			buf.append("\" suppressiontype=\"");
    135 			StringUtil.appendXmlEscaped(buf, s.suppressedByNOPMD() ? "nopmd" : "annotation");
    136 			buf.append("\" msg=\"");
    137 			StringUtil.appendXmlEscaped(buf, s.getRuleViolation().getDescription());
    138 			buf.append("\" usermsg=\"");
    139 			StringUtil.appendXmlEscaped(buf, s.getUserMessage() == null ? "" : s.getUserMessage());
    140 			buf.append("\"/>").append(PMD.EOL);
    141 			writer.write(buf.toString());
    142 		    }
    143 		}
    144
    145 		writer.write("</pmd>" + PMD.EOL);
    146     }
    147
    148     private void maybeAdd(String attr, String value, StringBuilder buf) {
    149 		if (value != null && value.length() > 0) {
    150 		    buf.append(' ').append(attr).append("=\"");
    151 		    StringUtil.appendXmlEscaped(buf, value);
    152 		    buf.append('"');
    153 		}
    154     }
    155
    156     private void createVersionAttr(StringBuilder buffer) {
    157     	buffer.append("<pmd version=\"").append(PMD.VERSION).append('"');
    158     }
    159
    160     private void createTimestampAttr(StringBuilder buffer) {
    161 		buffer.append(" timestamp=\"").append(new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss.SSS").format(new Date()))
    162 			.append('"');
    163     }
    164
    165     // FIXME: elapsed time not available until the end of the processing
    166     /*
    167     private String createTimeElapsedAttr(Report rpt) {
    168         Report.ReadableDuration d = new Report.ReadableDuration(rpt.getElapsedTimeInMillis());
    169         return " elapsedTime=\"" + d.getTime() + "\"";
    170     }
    171     */
    172 }