/*
* Created on Jul 19, 2007
*
* Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on
* an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the
* specific language governing permissions and limitations under the License.
*
* Copyright @2007-2009 the original author or authors.
*/
package org.fest.swing.junit.ant;
import static org.fest.util.Strings.concat;
import java.io.File;
import java.net.URL;
import java.util.List;
import java.util.concurrent.CopyOnWriteArrayList;
import org.apache.tools.ant.*;
import org.apache.tools.ant.taskdefs.*;
import org.apache.tools.ant.taskdefs.XSLTProcess.Param;
import org.apache.tools.ant.taskdefs.optional.junit.AggregateTransformer;
import org.apache.tools.ant.taskdefs.optional.junit.XMLResultAggregator;
import org.apache.tools.ant.types.*;
import org.apache.tools.ant.types.resources.FileResource;
import org.apache.tools.ant.types.resources.URLResource;
import org.apache.tools.ant.util.FileUtils;
/**
* Transforms a JUnit XML report. The default transformation generates an HTML report in either framed or non-framed
* style.
*
* @author Alex Ruiz
*/
public class ReportTransformer extends AggregateTransformer {
private static final String XSL_FILE_PATH = "org/fest/swing/junit/ant/";
private Path classpath;
/** The parameters that will be sent to the XSL transformation. */
private final List<Param> params;
/** Instance of a utility class to use for file operations. */
private static final FileUtils FILE_UTILS = FileUtils.getFileUtils();
/** Used to ensure the uniqueness of a property. */
private static int counter;
/**
* Creates a new <code>{@link ReportTransformer}</code>.
* @param task task delegating to this class.
*/
public ReportTransformer(Task task) {
super(task);
params = new CopyOnWriteArrayList<Param>();
}
/**
* Create an instance of an XSL parameter for configuration by Ant.
* @return an instance of the <code>Param</code> class to be configured.
*/
@Override public Param createParam() {
Param p = new Param();
params.add(p);
return p;
}
/**
* Performs the XSLT transformation to generate the HTML report.
* @throws BuildException thrown if something goes wrong with the transformation.
*/
@Override public void transform() throws BuildException {
checkOptions();
TempFile tempFileTask = tempFileTask();
XSLTProcess xsltTask = xsltTask();
File outputFile = outputFile(tempFileTask);
xsltTask.setOut(outputFile);
createNewParams(xsltTask);
createOutputDirParam(xsltTask);
long startingTime = System.currentTimeMillis();
try {
xsltTask.execute();
} catch (Exception e) {
throw new BuildException(concat("Errors while applying transformations: ", e.getMessage()), e);
}
long transformTime = System.currentTimeMillis() - startingTime;
task.log(concat("Transform time: ", String.valueOf(transformTime), " ms"));
delete(outputFile);
}
private XSLTProcess xsltTask() {
XSLTProcess xsltTask = new XSLTProcess();
xsltTask.bindToOwner(task);
xsltTask.setClasspath(classpath);
xsltTask.setXslResource(getStylesheet());
xsltTask.setIn(((XMLResultAggregator) task).getDestinationFile());
return xsltTask;
}
/**
* Access the stylesheet to be used as a resource.
* @return stylesheet as a resource
*/
@Override protected Resource getStylesheet() {
String xslname = "junit-frames.xsl";
if (NOFRAMES.equals(format)) xslname = "junit-noframes.xsl";
if (styleDir == null) {
URLResource stylesheet = new URLResource();
URL stylesheetURL = getClass().getClassLoader().getResource(concat(XSL_FILE_PATH, xslname));
stylesheet.setURL(stylesheetURL);
return stylesheet;
}
FileResource stylesheet = new FileResource();
File stylesheetFile = new File(styleDir, xslname);
stylesheet.setFile(stylesheetFile);
return stylesheet;
}
private TempFile tempFileTask() {
TempFile tempFileTask = new TempFile();
tempFileTask.bindToOwner(task);
return tempFileTask;
}
private File outputFile(TempFile tempFileTask) {
Project project = task.getProject();
if (format.equals(FRAMES)) {
String tempFileProperty = concat(getClass().getName(), String.valueOf(counter++));
setUpTempFileTask(tempFileTask, tempFileProperty);
return new File(project.getProperty(tempFileProperty));
}
return new File(toDir, "junit-noframes.html");
}
private void setUpTempFileTask(TempFile tempFileTask, String tempFileProperty) {
Project project = task.getProject();
File tmp = FILE_UTILS.resolveFile(project.getBaseDir(), project.getProperty("java.io.tmpdir"));
tempFileTask.setDestDir(tmp);
tempFileTask.setProperty(tempFileProperty);
tempFileTask.execute();
}
private void createNewParams(XSLTProcess xsltTask) {
for (Param param : params) {
Param p = xsltTask.createParam();
p.setProject(task.getProject());
p.setName(param.getName());
p.setExpression(param.getExpression());
}
}
private void createOutputDirParam(XSLTProcess xsltTask) {
Param p = xsltTask.createParam();
p.setProject(task.getProject());
p.setName("output.dir");
p.setExpression(toDir.getAbsolutePath());
}
private void delete(File outputFile) {
if (!format.equals(FRAMES)) return;
Delete deleteTask = new Delete();
deleteTask.bindToOwner(task);
deleteTask.setFile(outputFile);
deleteTask.execute();
}
/**
* Sets an additional classpath.
* @param classpath the additional classpath to append to the current one.
*/
public void setClasspath(Path classpath) {
createClasspath().append(classpath);
}
/**
* Sets a reference to a classpath.
* @param r the reference to set.
*/
public void setClasspathRef(Reference r) {
createClasspath().setRefid(r);
}
/**
* Creates the current classpath.
* @return the created classpath.
*/
public Path createClasspath() {
if (classpath == null) classpath = new Path(task.getProject());
return classpath.createPath();
}
}