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 }