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.XSLTRenderer;
    17  import net.sourceforge.pmd.renderers.YAHTMLRenderer;
    18  import net.sourceforge.pmd.renderers.CSVRenderer;
    19  import org.apache.tools.ant.BuildException;
    20
    21  import java.io.BufferedWriter;
    22  import java.io.File;
    23  import java.io.FileWriter;
    24  import java.io.IOException;
    25  import java.io.OutputStreamWriter;
    26  import java.io.Writer;
    27  import java.util.HashMap;
    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<String, RendererBuilder> renderersByCode = new HashMap<String, RendererBuilder>(8);
    44
    45      static {
    46          renderersByCode.put("xml", new RendererBuilder() {
    47              public Renderer build(Object[] arg) { return new XMLRenderer(); }
    48          });
    49          renderersByCode.put("betterhtml", new RendererBuilder() {
    50              public Renderer build(Object[] arg) { return new XSLTRenderer(); }
    51          });
    52          renderersByCode.put("html", new RendererBuilder() {
    53              public Renderer build(Object[] arg) { return new HTMLRenderer((String) arg[0], (String) arg[1]); }
    54          });
    55          renderersByCode.put("summaryhtml", new RendererBuilder() {
    56              public Renderer build(Object[] arg) { return new SummaryHTMLRenderer((String) arg[0], (String) arg[1]); }
    57          });
    58          renderersByCode.put("papari", new RendererBuilder() {
    59              public Renderer build(Object[] arg) { return new PapariTextRenderer(); }
    60          });
    61          renderersByCode.put("csv", new RendererBuilder() {
    62              public Renderer build(Object[] arg) { return new CSVRenderer(); }
    63          });
    64          renderersByCode.put("emacs", new RendererBuilder() {
    65              public Renderer build(Object[] arg) { return new EmacsRenderer(); }
    66          });
    67          renderersByCode.put("vbhtml", new RendererBuilder() {
    68              public Renderer build(Object[] arg) { return new VBHTMLRenderer(); }
    69          });
    70          renderersByCode.put("yahtml", new RendererBuilder() {
    71              public Renderer build(Object[] arg) { return new YAHTMLRenderer(); }
    72          });
    73          renderersByCode.put("text", new RendererBuilder() {
    74              public Renderer build(Object[] arg) { return new TextRenderer(); }
    75          });
    76          // add additional codes & factories here
    77      }
    78
    79      public void setShowSuppressed(boolean value) {
    80          this.showSuppressed = value;
    81      }
    82
    83      public void setType(String type) {
    84          this.type = type;
    85      }
    86
    87      public void setLinkPrefix(String linkPrefix) {
    88          this.linkPrefix = linkPrefix;
    89      }
    90
    91      public void setToFile(File toFile) {
    92          this.toFile = toFile;
    93      }
    94
    95      public void setToConsole(boolean toConsole) {
    96          this.toConsole = toConsole;
    97      }
    98
    99      public void setLinePrefix(String linePrefix) {
    100         this.linePrefix = linePrefix;
    101     }
    102
    103     private Writer writer;
    104
    105     private Renderer renderer;
    106
    107     public Renderer getRenderer() {
    108         return renderer;
    109     }
    110
    111     public void start(String baseDir) {
    112         try {
    113             if (toConsole) {
    114                 writer = new BufferedWriter(new OutputStreamWriter(System.out));
    115             }
    116             if (toFile != null) {
    117                 writer = getToFileWriter(baseDir);
    118             }
    119             renderer = getRenderer(toConsole);
    120             renderer.setWriter(writer);
    121             renderer.start();
    122         } catch (IOException ioe) {
    123             throw new BuildException(ioe.getMessage());
    124         }
    125     }
    126
    127     public void end(Report errorReport) {
    128         try {
    129             renderer.renderFileReport(errorReport);
    130             renderer.end();
    131             writer.write(PMD.EOL);
    132             if (toConsole) {
    133                 writer.flush();
    134             } else {
    135                 writer.close();
    136             }
    137         } catch (IOException ioe) {
    138             throw new BuildException(ioe.getMessage());
    139         }
    140     }
    141
    142     public boolean isNoOutputSupplied() {
    143         return toFile == null && !toConsole;
    144     }
    145
    146     public String toString() {
    147         return "file = " + toFile + "; renderer = " + type;
    148     }
    149
    150     private static String[] validRendererCodes() {
    151         return renderersByCode.keySet().toArray(new String[renderersByCode.size()]);
    152     }
    153
    154     private static String unknownRendererMessage(String userSpecifiedType) {
    155         StringBuffer sb = new StringBuffer(100);
    156         sb.append("Formatter type must be one of: '");
    157         String[] typeCodes = validRendererCodes();
    158         sb.append(typeCodes[0]);
    159         for (int i = 1; i < typeCodes.length; i++) {
    160             sb.append("', '").append(typeCodes[i]);
    161         }
    162         sb.append("', or a class name; you specified: ");
    163         sb.append(userSpecifiedType);
    164         return sb.toString();
    165     }
    166
    167     private Renderer fromClassname(String rendererClassname) {
    168         try {
    169             return (Renderer) Class.forName(rendererClassname).newInstance();
    170         } catch (Exception e) {
    171             throw new BuildException(unknownRendererMessage(rendererClassname));
    172         }
    173     }
    174
    175     // FIXME - hm, what about this consoleRenderer thing... need a test for this
    176     private Renderer getRenderer(boolean consoleRenderer) {
    177         if ("".equals(type)) {
    178             throw new BuildException(unknownRendererMessage("<unspecified>"));
    179         }
    180         RendererBuilder builder = renderersByCode.get(type);
    181         Renderer renderer = builder == null ? fromClassname(type) : builder.build(new String[]{linkPrefix, linePrefix});
    182         renderer.showSuppressedViolations(showSuppressed);
    183         return renderer;
    184     }
    185
    186     private Writer getToFileWriter(String baseDir) throws IOException {
    187         if (!toFile.isAbsolute()) {
    188             return new BufferedWriter(new FileWriter(new File(baseDir + System.getProperty("file.separator") + toFile.getPath())));
    189         }
    190         return new BufferedWriter(new FileWriter(toFile));
    191     }
    192 }