View Javadoc

    1   /***
    2    * BSD-style license; for more info see http://pmd.sourceforge.net/license.html
    3    */
    4   package net.sourceforge.pmd.ant;
    5
    6   import net.sourceforge.pmd.PMD;
    7   import net.sourceforge.pmd.Report;
    8   import net.sourceforge.pmd.renderers.EmacsRenderer;
    9   import net.sourceforge.pmd.renderers.HTMLRenderer;
    10  import net.sourceforge.pmd.renderers.PapariTextRenderer;
    11  import net.sourceforge.pmd.renderers.Renderer;
    12  import net.sourceforge.pmd.renderers.SummaryHTMLRenderer;
    13  import net.sourceforge.pmd.renderers.TextRenderer;
    14  import net.sourceforge.pmd.renderers.VBHTMLRenderer;
    15  import net.sourceforge.pmd.renderers.XMLRenderer;
    16  import net.sourceforge.pmd.renderers.YAHTMLRenderer;
    17  import net.sourceforge.pmd.renderers.CSVRenderer;
    18  import org.apache.tools.ant.BuildException;
    19
    20  import java.io.BufferedWriter;
    21  import java.io.File;
    22  import java.io.FileWriter;
    23  import java.io.IOException;
    24  import java.io.OutputStreamWriter;
    25  import java.io.Writer;
    26  import java.util.HashMap;
    27  import java.util.Iterator;
    28  import java.util.Map;
    29
    30  public class Formatter {
    31
    32      private interface RendererBuilder {
    33          Renderer build(Object[] optionalArg);
    34      } // factory template
    35
    36      private File toFile;
    37      private String linkPrefix;
    38      private String linePrefix;
    39      private String type;
    40      private boolean toConsole;
    41      private boolean showSuppressed;
    42
    43      private static final Map renderersByCode = new HashMap(8);
    44
    45      static {
    46          renderersByCode.put("xml", new RendererBuilder() {
    47              public Renderer build(Object[] arg) { return new XMLRenderer(); }
    48          });
    49          renderersByCode.put("html", new RendererBuilder() {
    50              public Renderer build(Object[] arg) { return new HTMLRenderer((String) arg[0], (String) arg[1]); }
    51          });
    52          renderersByCode.put("summaryhtml", new RendererBuilder() {
    53              public Renderer build(Object[] arg) { return new SummaryHTMLRenderer((String) arg[0], (String) arg[1]); }
    54          });
    55          renderersByCode.put("papari", new RendererBuilder() {
    56              public Renderer build(Object[] arg) { return new PapariTextRenderer(); }
    57          });
    58          renderersByCode.put("csv", new RendererBuilder() {
    59              public Renderer build(Object[] arg) { return new CSVRenderer(); }
    60          });
    61          renderersByCode.put("emacs", new RendererBuilder() {
    62              public Renderer build(Object[] arg) { return new EmacsRenderer(); }
    63          });
    64          renderersByCode.put("vbhtml", new RendererBuilder() {
    65              public Renderer build(Object[] arg) { return new VBHTMLRenderer(); }
    66          });
    67          renderersByCode.put("yahtml", new RendererBuilder() {
    68              public Renderer build(Object[] arg) { return new YAHTMLRenderer(); }
    69          });
    70          renderersByCode.put("text", new RendererBuilder() {
    71              public Renderer build(Object[] arg) { return new TextRenderer(); }
    72          });
    73          // add additional codes & factories here
    74      }
    75
    76      public void setShowSuppressed(boolean value) {
    77          this.showSuppressed = value;
    78      }
    79
    80      public void setType(String type) {
    81          this.type = type;
    82      }
    83
    84      public void setLinkPrefix(String linkPrefix) {
    85          this.linkPrefix = linkPrefix;
    86      }
    87
    88      public void setToFile(File toFile) {
    89          this.toFile = toFile;
    90      }
    91
    92      public void setToConsole(boolean toConsole) {
    93          this.toConsole = toConsole;
    94      }
    95
    96      public void setLinePrefix(String linePrefix) {
    97          this.linePrefix = linePrefix;
    98      }
    99
    100     public void outputReport(Report report, String baseDir) {
    101         try {
    102             if (toConsole) {
    103                 outputReportTo(new BufferedWriter(new OutputStreamWriter(System.out)), report, true);
    104             }
    105             if (toFile != null) {
    106                 outputReportTo(getToFileWriter(baseDir), report, false);
    107             }
    108         } catch (IOException ioe) {
    109             throw new BuildException(ioe.getMessage());
    110         }
    111     }
    112
    113     public boolean isNoOutputSupplied() {
    114         return toFile == null && !toConsole;
    115     }
    116
    117     public String toString() {
    118         return "file = " + toFile + "; renderer = " + type;
    119     }
    120
    121     private static String[] validRendererCodes() {
    122         Iterator iter = renderersByCode.keySet().iterator();
    123         String[] validTypes = new String[renderersByCode.size()];
    124         int i = 0;
    125         while (iter.hasNext()) validTypes[i++] = (String) iter.next();
    126         return validTypes;
    127     }
    128
    129     private void outputReportTo(Writer writer, Report report, boolean consoleRenderer) throws IOException {
    130         getRenderer(consoleRenderer).render(writer, report);
    131         writer.write(PMD.EOL);
    132         writer.close();
    133     }
    134
    135
    136     private static String unknownRendererMessage(String userSpecifiedType) {
    137         StringBuffer sb = new StringBuffer(100);
    138         sb.append("Formatter type must be one of: '");
    139         String[] typeCodes = validRendererCodes();
    140         sb.append(typeCodes[0]);
    141         for (int i = 1; i < typeCodes.length; i++) {
    142             sb.append("', '").append(typeCodes[i]);
    143         }
    144         sb.append("', or a class name; you specified: ");
    145         sb.append(userSpecifiedType);
    146         return sb.toString();
    147     }
    148
    149     private Renderer fromClassname(String rendererClassname) {
    150         try {
    151             return (Renderer) Class.forName(rendererClassname).newInstance();
    152         } catch (Exception e) {
    153             throw new BuildException(unknownRendererMessage(rendererClassname));
    154         }
    155     }
    156
    157     // FIXME - hm, what about this consoleRenderer thing... need a test for this
    158     private Renderer getRenderer(boolean consoleRenderer) {
    159         if ("".equals(type)) {
    160             throw new BuildException(unknownRendererMessage("<unspecified>"));
    161         }
    162         RendererBuilder builder = (RendererBuilder) renderersByCode.get(type);
    163         Renderer renderer = builder == null ? fromClassname(type) : builder.build(new String[]{linkPrefix, linePrefix});
    164         renderer.showSuppressedViolations(showSuppressed);
    165         return renderer;
    166     }
    167
    168     private Writer getToFileWriter(String baseDir) throws IOException {
    169         if (!toFile.isAbsolute()) {
    170             return new BufferedWriter(new FileWriter(new File(baseDir + System.getProperty("file.separator") + toFile.getPath())));
    171         }
    172         return new BufferedWriter(new FileWriter(toFile));
    173     }
    174 }