001 /*
002 * Created on Jul 19, 2007
003 *
004 * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with
005 * the License. You may obtain a copy of the License at
006 *
007 * http://www.apache.org/licenses/LICENSE-2.0
008 *
009 * Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on
010 * an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the
011 * specific language governing permissions and limitations under the License.
012 *
013 * Copyright @2007-2009 the original author or authors.
014 */
015 package org.fest.swing.junit.ant;
016
017 import static org.fest.util.Strings.concat;
018
019 import java.io.File;
020 import java.net.URL;
021 import java.util.List;
022 import java.util.concurrent.CopyOnWriteArrayList;
023
024 import org.apache.tools.ant.*;
025 import org.apache.tools.ant.taskdefs.*;
026 import org.apache.tools.ant.taskdefs.XSLTProcess.Param;
027 import org.apache.tools.ant.taskdefs.optional.junit.AggregateTransformer;
028 import org.apache.tools.ant.taskdefs.optional.junit.XMLResultAggregator;
029 import org.apache.tools.ant.types.*;
030 import org.apache.tools.ant.types.resources.FileResource;
031 import org.apache.tools.ant.types.resources.URLResource;
032 import org.apache.tools.ant.util.FileUtils;
033
034 /**
035 * Transforms a JUnit XML report. The default transformation generates an HTML report in either framed or non-framed
036 * style.
037 *
038 * @author Alex Ruiz
039 */
040 public class ReportTransformer extends AggregateTransformer {
041
042 private static final String XSL_FILE_PATH = "org/fest/swing/junit/ant/";
043
044 private Path classpath;
045
046 /** The parameters that will be sent to the XSL transformation. */
047 private final List<Param> params;
048
049 /** Instance of a utility class to use for file operations. */
050 private static final FileUtils FILE_UTILS = FileUtils.getFileUtils();
051
052 /** Used to ensure the uniqueness of a property. */
053 private static int counter;
054
055 /**
056 * Creates a new <code>{@link ReportTransformer}</code>.
057 * @param task task delegating to this class.
058 */
059 public ReportTransformer(Task task) {
060 super(task);
061 params = new CopyOnWriteArrayList<Param>();
062 }
063
064 /**
065 * Create an instance of an XSL parameter for configuration by Ant.
066 * @return an instance of the <code>Param</code> class to be configured.
067 */
068 @Override public Param createParam() {
069 Param p = new Param();
070 params.add(p);
071 return p;
072 }
073
074 /**
075 * Performs the XSLT transformation to generate the HTML report.
076 * @throws BuildException thrown if something goes wrong with the transformation.
077 */
078 @Override public void transform() throws BuildException {
079 checkOptions();
080 TempFile tempFileTask = tempFileTask();
081 XSLTProcess xsltTask = xsltTask();
082 File outputFile = outputFile(tempFileTask);
083 xsltTask.setOut(outputFile);
084 createNewParams(xsltTask);
085 createOutputDirParam(xsltTask);
086 long startingTime = System.currentTimeMillis();
087 try {
088 xsltTask.execute();
089 } catch (Exception e) {
090 throw new BuildException(concat("Errors while applying transformations: ", e.getMessage()), e);
091 }
092 long transformTime = System.currentTimeMillis() - startingTime;
093 task.log(concat("Transform time: ", String.valueOf(transformTime), " ms"));
094 delete(outputFile);
095 }
096
097 private XSLTProcess xsltTask() {
098 XSLTProcess xsltTask = new XSLTProcess();
099 xsltTask.bindToOwner(task);
100 xsltTask.setClasspath(classpath);
101 xsltTask.setXslResource(getStylesheet());
102 xsltTask.setIn(((XMLResultAggregator) task).getDestinationFile());
103 return xsltTask;
104 }
105
106 /**
107 * Access the stylesheet to be used as a resource.
108 * @return stylesheet as a resource
109 */
110 @Override protected Resource getStylesheet() {
111 String xslname = "junit-frames.xsl";
112 if (NOFRAMES.equals(format)) xslname = "junit-noframes.xsl";
113 if (styleDir == null) {
114 URLResource stylesheet = new URLResource();
115 URL stylesheetURL = getClass().getClassLoader().getResource(concat(XSL_FILE_PATH, xslname));
116 stylesheet.setURL(stylesheetURL);
117 return stylesheet;
118 }
119 FileResource stylesheet = new FileResource();
120 File stylesheetFile = new File(styleDir, xslname);
121 stylesheet.setFile(stylesheetFile);
122 return stylesheet;
123 }
124
125 private TempFile tempFileTask() {
126 TempFile tempFileTask = new TempFile();
127 tempFileTask.bindToOwner(task);
128 return tempFileTask;
129 }
130
131 private File outputFile(TempFile tempFileTask) {
132 Project project = task.getProject();
133 if (format.equals(FRAMES)) {
134 String tempFileProperty = concat(getClass().getName(), String.valueOf(counter++));
135 setUpTempFileTask(tempFileTask, tempFileProperty);
136 return new File(project.getProperty(tempFileProperty));
137 }
138 return new File(toDir, "junit-noframes.html");
139 }
140
141 private void setUpTempFileTask(TempFile tempFileTask, String tempFileProperty) {
142 Project project = task.getProject();
143 File tmp = FILE_UTILS.resolveFile(project.getBaseDir(), project.getProperty("java.io.tmpdir"));
144 tempFileTask.setDestDir(tmp);
145 tempFileTask.setProperty(tempFileProperty);
146 tempFileTask.execute();
147 }
148
149 private void createNewParams(XSLTProcess xsltTask) {
150 for (Param param : params) {
151 Param p = xsltTask.createParam();
152 p.setProject(task.getProject());
153 p.setName(param.getName());
154 p.setExpression(param.getExpression());
155 }
156 }
157
158 private void createOutputDirParam(XSLTProcess xsltTask) {
159 Param p = xsltTask.createParam();
160 p.setProject(task.getProject());
161 p.setName("output.dir");
162 p.setExpression(toDir.getAbsolutePath());
163 }
164
165 private void delete(File outputFile) {
166 if (!format.equals(FRAMES)) return;
167 Delete deleteTask = new Delete();
168 deleteTask.bindToOwner(task);
169 deleteTask.setFile(outputFile);
170 deleteTask.execute();
171 }
172
173 /**
174 * Sets an additional classpath.
175 * @param classpath the additional classpath to append to the current one.
176 */
177 public void setClasspath(Path classpath) {
178 createClasspath().append(classpath);
179 }
180
181 /**
182 * Sets a reference to a classpath.
183 * @param r the reference to set.
184 */
185 public void setClasspathRef(Reference r) {
186 createClasspath().setRefid(r);
187 }
188
189 /**
190 * Creates the current classpath.
191 * @return the created classpath.
192 */
193 public Path createClasspath() {
194 if (classpath == null) classpath = new Path(task.getProject());
195 return classpath.createPath();
196 }
197 }