1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17 package org.woopi.ant.taskdefs.junit;
18 import java.io.File;
19 import java.io.FileInputStream;
20 import java.io.FileNotFoundException;
21 import java.io.IOException;
22 import java.io.InputStream;
23 import java.net.URL;
24 import javax.xml.parsers.DocumentBuilder;
25 import javax.xml.parsers.DocumentBuilderFactory;
26 import org.apache.tools.ant.BuildException;
27 import org.apache.tools.ant.Project;
28 import org.apache.tools.ant.Task;
29 import org.apache.tools.ant.util.JAXPUtils;
30 import org.apache.tools.ant.types.EnumeratedAttribute;
31 import org.w3c.dom.Document;
32
33 /***
34 * Transform a JUnit xml report.
35 * The default transformation generates an html report in either framed or non-framed
36 * style. The non-framed style is convenient to have a concise report via mail, the
37 * framed report is much more convenient if you want to browse into different
38 * packages or testcases since it is a Javadoc like report.
39 *
40 */
41 public class AggregateTransformer {
42
43 public static final String FRAMES = "frames";
44
45 public static final String NOFRAMES = "noframes";
46
47 public static class Format extends EnumeratedAttribute {
48 public String[] getValues() {
49 return new String[]{FRAMES, NOFRAMES};
50 }
51 }
52
53 /*** Task */
54 protected Task task;
55
56 /*** the xml document to process */
57 protected Document document;
58
59 /*** the style directory. XSLs should be read from here if necessary */
60 protected File styleDir;
61
62 /*** the destination directory, this is the root from where html should be generated */
63 protected File toDir;
64
65 /*** the format to use for the report. Must be <tt>FRAMES</tt> or <tt>NOFRAMES</tt> */
66 protected String format = FRAMES;
67
68 /*** XML Parser factory */
69 private static DocumentBuilderFactory privateDBFactory;
70
71 /*** XML Parser factory accessible to subclasses */
72 protected static DocumentBuilderFactory dbfactory;
73
74 static {
75 privateDBFactory = DocumentBuilderFactory.newInstance();
76 dbfactory = privateDBFactory;
77 }
78
79 public AggregateTransformer(Task task) {
80 this.task = task;
81 }
82
83 /***
84 * Get the Document Builder Factory
85 *
86 * @return the DocumentBuilderFactory instance in use
87 */
88 protected static DocumentBuilderFactory getDocumentBuilderFactory() {
89 return privateDBFactory;
90 }
91
92 public void setFormat(Format format) {
93 this.format = format.getValue();
94 }
95
96 public void setXmlDocument(Document doc) {
97 this.document = doc;
98 }
99
100 /***
101 * Set the xml file to be processed. This is a helper if you want
102 * to set the file directly. Much more for testing purposes.
103 * @param xmlfile xml file to be processed
104 */
105 protected void setXmlfile(File xmlfile) throws BuildException {
106 try {
107 DocumentBuilder builder = privateDBFactory.newDocumentBuilder();
108 InputStream in = new FileInputStream(xmlfile);
109 try {
110 Document doc = builder.parse(in);
111 setXmlDocument(doc);
112 } finally {
113 in.close();
114 }
115 } catch (Exception e) {
116 throw new BuildException("Error while parsing document: " + xmlfile, e);
117 }
118 }
119
120 /***
121 * set the style directory. It is optional and will override the
122 * default xsl used.
123 * @param styledir the directory containing the xsl files if the user
124 * would like to override with its own style.
125 */
126 public void setStyledir(File styledir) {
127 this.styleDir = styledir;
128 }
129
130 /*** set the destination directory */
131 public void setTodir(File todir) {
132 this.toDir = todir;
133 }
134
135 /*** set the extension of the output files */
136 public void setExtension(String ext) {
137 task.log("extension is not used anymore", Project.MSG_WARN);
138 }
139
140 public void transform() throws BuildException {
141 checkOptions();
142 final long t0 = System.currentTimeMillis();
143 XalanExecutor executor = XalanExecutor.newInstance(this);
144 try {
145 executor.execute();
146 } catch (Exception e) {
147 throw new BuildException("Errors while applying transformations: "
148 + e.getMessage(), e);
149 }
150 final long dt = System.currentTimeMillis() - t0;
151 task.log("Transform time: " + dt + "ms");
152 }
153
154 /*** check for invalid options */
155 protected void checkOptions() throws BuildException {
156
157 if (toDir == null) {
158 toDir = task.getProject().resolveFile(".");
159 } else if (!toDir.isAbsolute()) {
160 toDir = task.getProject().resolveFile(toDir.getPath());
161 }
162 }
163
164 /***
165 * Get the systemid of the appropriate stylesheet based on its
166 * name and styledir. If no styledir is defined it will load
167 * it as a java resource in the xsl child package, otherwise it
168 * will get it from the given directory.
169 * @throws IOException thrown if the requested stylesheet does
170 * not exist.
171 */
172 protected String getStylesheetSystemId() throws IOException {
173 String xslname = "junit-frames.xsl";
174 if (NOFRAMES.equals(format)) {
175 xslname = "junit-noframes.xsl";
176 }
177 if (styleDir == null) {
178 URL url = getClass().getResource("xsl/" + xslname);
179 if (url == null) {
180 throw new FileNotFoundException("Could not find jar resource " + xslname);
181 }
182 return url.toExternalForm();
183 }
184 File file = new File(styleDir, xslname);
185 if (!file.exists()) {
186 throw new FileNotFoundException("Could not find file '" + file + "'");
187 }
188 return JAXPUtils.getSystemId(file);
189 }
190
191 }