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 }