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 }
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
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
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 }