diff --git a/WHATSNEW b/WHATSNEW index f9964f83e..43ec62a77 100644 --- a/WHATSNEW +++ b/WHATSNEW @@ -450,6 +450,8 @@ Other changes: * now supports an outputencoding attribute. Bugzilla report 39697. +* now supports nested XSL parameters. Bugzilla report 39708. + Changes from Ant 1.6.4 to Ant 1.6.5 =================================== diff --git a/docs/manual/OptionalTasks/junitreport.html b/docs/manual/OptionalTasks/junitreport.html index 1450f05d0..f632c04a2 100644 --- a/docs/manual/OptionalTasks/junitreport.html +++ b/docs/manual/OptionalTasks/junitreport.html @@ -95,6 +95,40 @@ element.

No. Default to current directory +

Nested Element of the report tag

+

param

+Since Ant 1.7the report tag supports nested param tags. +These tags can pass XSL parameters to the stylesheet. +

Parameters

+ + + + + + + + + + + + + + + + + + + + + + + + + + + +
AttributeDescriptionRequired
nameName of the XSL parameterYes
expressionText value to be placed into the param.
+ Was originally intended to be an XSL expression.
Yes
ifThe param will only passed if this property is set.No
unlessThe param will only passed unless this property is set.No

Example of report

<junitreport todir="./reports">
@@ -107,9 +141,26 @@ element.

would generate a TESTS-TestSuites.xml file in the directory reports and generate the default framed report in the directory report/html.

- +

Example of report with xsl params

+
+
+<junitreport todir="${outputdir}">
+    <fileset dir="${jrdir}">
+        <include name="TEST-*.xml"/>
+    </fileset>
+    <report todir="${outputdir}/html"
+        styledir="junitreport"
+        format="frames">
+        <param name="key1" expression="value1"/>
+        <param name="key2" expression="value2"/>
+    </report>
+</junitreport>
+  
+
+

This example requires a file called junitreport/junit-frames.xsl. + The XSL parameters key1 and key2 will be passed to the XSL transformation.


-

Copyright © 2001-2002,2004-2005 The Apache Software Foundation. All rights +

Copyright © 2001-2002,2004-2006 The Apache Software Foundation. All rights Reserved.

diff --git a/src/etc/testcases/taskdefs/optional/junitreport.xml b/src/etc/testcases/taskdefs/optional/junitreport.xml index 15cb67cc5..dedf44f3f 100644 --- a/src/etc/testcases/taskdefs/optional/junitreport.xml +++ b/src/etc/testcases/taskdefs/optional/junitreport.xml @@ -105,4 +105,45 @@
- \ No newline at end of file + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/src/etc/testcases/taskdefs/optional/junitreport/junit-frames.xsl b/src/etc/testcases/taskdefs/optional/junitreport/junit-frames.xsl new file mode 100644 index 000000000..81aecb28c --- /dev/null +++ b/src/etc/testcases/taskdefs/optional/junitreport/junit-frames.xsl @@ -0,0 +1,877 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + . + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + Unit Test Results. key1=<xsl:value-of select="$key1"/>,key2=<xsl:value-of select="$key2"/> + + + + + + + + + + <h2>Frame Alert</h2> + <p> + This document is designed to be viewed using the frames feature. If you see this message, you are using a non-frame-capable web client. + </p> + + + + + + + +body { + font:normal 68% verdana,arial,helvetica; + color:#000000; +} +table tr td, table tr th { + font-size: 68%; +} +table.details tr th{ + font-weight: bold; + text-align:left; + background:#a6caf0; +} +table.details tr td{ + background:#eeeee0; +} + +p { + line-height:1.5em; + margin-top:0.5em; margin-bottom:1.0em; +} +h1 { + margin: 0px 0px 5px; font: 165% verdana,arial,helvetica +} +h2 { + margin-top: 1em; margin-bottom: 0.5em; font: bold 125% verdana,arial,helvetica +} +h3 { + margin-bottom: 0.5em; font: bold 115% verdana,arial,helvetica +} +h4 { + margin-bottom: 0.5em; font: bold 100% verdana,arial,helvetica +} +h5 { + margin-bottom: 0.5em; font: bold 100% verdana,arial,helvetica +} +h6 { + margin-bottom: 0.5em; font: bold 100% verdana,arial,helvetica +} +.Error { + font-weight:bold; color:red; +} +.Failure { + font-weight:bold; color:purple; +} +.Properties { + text-align:right; +} + + + + + + + + + + All Failures + + + All Errors + + + All Tests + + + + + Unit Test Results: <xsl:value-of select="$title"/> + + + + + + open('allclasses-frame.html','classListFrame') + +

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+ + +
+ + + + + + + . + + + Unit Test Results: <xsl:value-of select="$class.name"/> + + + + + + + + +

Class

+ + + + + +
+ + + +

Failures

+
+ +

Errors

+
+ +

Tests

+
+
+ + + + + + + + + + + + + + + + + + + +
+ + + + + + + + + +
+ + + + cur = TestCases['.'] = new Array(); + + + cur[''] = ''; + + + + + + + + + + + Unit Test Classes: <xsl:value-of select="$name"/> + + + + + + + + + +
+

+ + <none> +

+
+ +

Classes

+ + + + + + + +
+ +
+ + +
+ + + + + + + All Unit Test Classes + + + + + +

Classes

+ + + + +
+ + +
+ + + + + + + + + / + _.html + + + + + + + + + + + + + All Unit Test Packages + + + + + +

Home

+

Packages

+ + + + +
+ + +
+ + + + + + + <none> + + + + + + + + + + Unit Test Results: Summary + + + + + + open('allclasses-frame.html','classListFrame') + +

Summary

+ + + + + + + + + + + + + + + + + Error + Failure + Pass + + + + + + + + +
TestsFailuresErrorsSuccess rateTime
+ + + + + + + +
+ + + + +
+ Note: failures are anticipated and checked for with assertions while errors are unanticipated. +
+ +

Packages

+ + + + + + + + + + + Error + Failure + Pass + + + + + + + + + + + +
+ + <none> + + + + +
+ + +
+ + + + + + + + + + + + open('package-frame.html','classListFrame') + +

Package

+ + + + + +

Classes

+

+ + + + + +
+

+
+ + +
+ + + + + + + ../ + + + + + + ../ + + + + + + + + stylesheet.css + + + + + +

Unit Test Results

+ + + + + +
Designed for use with JUnit and Ant.
+
+
+ + + + + Name + Tests + Errors + Failures + Time(s) + Time Stamp + Host + + + + + + + + + Class + + Name + Status + Type + Time(s) + + + + + + + + + + Error + Failure + Pass + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + Error + Failure + TableRowColor + + + + + + + + + + + + + + + + + + + + + + Failure + + + + Error + + + + Success + + + + + + + + + + + + + + + + + + + + + + + + + N/A + + + + + +

+ + + + + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + +
diff --git a/src/main/org/apache/tools/ant/taskdefs/optional/junit/AggregateTransformer.java b/src/main/org/apache/tools/ant/taskdefs/optional/junit/AggregateTransformer.java index 98e6d08fe..b99783d4e 100644 --- a/src/main/org/apache/tools/ant/taskdefs/optional/junit/AggregateTransformer.java +++ b/src/main/org/apache/tools/ant/taskdefs/optional/junit/AggregateTransformer.java @@ -1,5 +1,5 @@ /* - * Copyright 2001-2002,2004 The Apache Software Foundation + * Copyright 2001-2002,2004,2006 The Apache Software Foundation * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -21,14 +21,29 @@ import java.io.FileInputStream; import java.io.FileNotFoundException; import java.io.IOException; import java.io.InputStream; + import java.net.URL; + +import java.util.Iterator; +import java.util.List; +import java.util.Vector; + import javax.xml.parsers.DocumentBuilder; import javax.xml.parsers.DocumentBuilderFactory; + import org.apache.tools.ant.BuildException; import org.apache.tools.ant.Project; import org.apache.tools.ant.Task; +import org.apache.tools.ant.taskdefs.XSLTProcess; +import org.apache.tools.ant.taskdefs.Delete; +import org.apache.tools.ant.taskdefs.TempFile; import org.apache.tools.ant.util.JAXPUtils; +import org.apache.tools.ant.util.FileUtils; import org.apache.tools.ant.types.EnumeratedAttribute; +import org.apache.tools.ant.types.Resource; +import org.apache.tools.ant.types.resources.URLResource; +import org.apache.tools.ant.types.resources.FileResource; + import org.w3c.dom.Document; /** @@ -40,12 +55,24 @@ import org.w3c.dom.Document; * */ public class AggregateTransformer { - + /** + * name of the frames format. + */ public static final String FRAMES = "frames"; + /** + * name of the no frames format. + */ public static final String NOFRAMES = "noframes"; + /** + * defines acceptable formats. + */ public static class Format extends EnumeratedAttribute { + /** + * list authorized values. + * @return authorized values. + */ public String[] getValues() { return new String[]{FRAMES, NOFRAMES}; } @@ -63,6 +90,25 @@ public class AggregateTransformer { /** the destination directory, this is the root from where html should be generated */ protected File toDir; + /** + * The params that will be sent to the XSL transformation + * + * @since Ant 1.7 + */ + private List params; + + /** + * Instance of a utility class to use for file operations. + * + * @since Ant 1.7 + */ + private static final FileUtils FILE_UTILS = FileUtils.getFileUtils(); + + /** + * Used to ensure the uniqueness of a property + */ + private static int counter = 0; + /** the format to use for the report. Must be FRAMES or NOFRAMES */ protected String format = FRAMES; @@ -77,8 +123,13 @@ public class AggregateTransformer { dbfactory = privateDBFactory; } + /** + * constructor creating the transformer from the junitreport task. + * @param task task delegating to this class + */ public AggregateTransformer(Task task) { this.task = task; + params = new Vector(); } /** @@ -90,10 +141,18 @@ public class AggregateTransformer { return privateDBFactory; } + /** + * sets the format. + * @param format Must be FRAMES or NOFRAMES + */ public void setFormat(Format format) { this.format = format.getValue(); } + /** + * sets the input document. + * @param doc input dom tree + */ public void setXmlDocument(Document doc) { this.document = doc; } @@ -102,6 +161,7 @@ public class AggregateTransformer { * Set the xml file to be processed. This is a helper if you want * to set the file directly. Much more for testing purposes. * @param xmlfile xml file to be processed + * @throws BuildException if the document cannot be parsed. */ protected void setXmlfile(File xmlfile) throws BuildException { try { @@ -128,31 +188,113 @@ public class AggregateTransformer { this.styleDir = styledir; } - /** set the destination directory */ + /** set the destination directory. + * @param todir the destination directory + */ public void setTodir(File todir) { this.toDir = todir; } - /** set the extension of the output files */ + /** set the extension of the output files + * @param ext extension. + */ public void setExtension(String ext) { task.log("extension is not used anymore", Project.MSG_WARN); } + /** + * Create an instance of an XSL parameter for configuration by Ant. + * + * @return an instance of the Param class to be configured. + * @since Ant 1.7 + */ + public XSLTProcess.Param createParam() { + XSLTProcess.Param p = new XSLTProcess.Param(); + params.add(p); + return p; + } + + /** + * transformation + * @throws BuildException exception if something goes wrong with the transformation. + */ public void transform() throws BuildException { checkOptions(); + Project project = task.getProject(); + + TempFile tempFileTask = new TempFile(); + tempFileTask.bindToOwner(task); + String tempFileProperty = getClass().getName() + String.valueOf(counter++); + File tmp = FILE_UTILS.resolveFile(project.getBaseDir(), + project.getProperty("java.io.tmpdir")); + tempFileTask.setDestDir(tmp); + tempFileTask.setProperty(tempFileProperty); + tempFileTask.execute(); + + XSLTProcess xsltTask = new XSLTProcess(); + xsltTask.bindToOwner(task); + + xsltTask.addConfigured(getStylesheet()); + // acrobatic cast. + xsltTask.setIn(((XMLResultAggregator) task).getDestinationFile()); + File dummyFile = new File(project.getProperty(tempFileProperty)); + xsltTask.setOut(dummyFile); + for (Iterator i = params.iterator(); i.hasNext();) { + XSLTProcess.Param param = (XSLTProcess.Param) i.next(); + XSLTProcess.Param newParam = xsltTask.createParam(); + newParam.setProject(task.getProject()); + newParam.setName(param.getName()); + newParam.setExpression(param.getExpression()); + } + XSLTProcess.Param paramx = xsltTask.createParam(); + paramx.setProject(task.getProject()); + paramx.setName("output.dir"); + paramx.setExpression(toDir.getAbsolutePath()); final long t0 = System.currentTimeMillis(); - XalanExecutor executor = XalanExecutor.newInstance(this); try { - executor.execute(); + xsltTask.execute(); } catch (Exception e) { throw new BuildException("Errors while applying transformations: " - + e.getMessage(), e); + + e.getMessage(), e); } final long dt = System.currentTimeMillis() - t0; task.log("Transform time: " + dt + "ms"); + Delete delete = new Delete(); + delete.bindToOwner(task); + delete.setFile(dummyFile); + delete.execute(); } - /** check for invalid options */ + /** + * access the stylesheet to be used as a resource. + * @return stylesheet as a resource + */ + protected Resource getStylesheet() { + String xslname = "junit-frames.xsl"; + if (NOFRAMES.equals(format)) { + xslname = "junit-noframes.xsl"; + } + if (styleDir == null) { + // If style dir is not specified we have to retrieve + // the stylesheet from the classloader + URLResource stylesheet = new URLResource(); + URL stylesheetURL = getClass().getClassLoader().getResource( + "org/apache/tools/ant/taskdefs/optional/junit/xsl/" + xslname); + stylesheet.setURL(stylesheetURL); + return stylesheet; + } + // If we are here, then the style dir is here and we + // should read the stylesheet from the filesystem + FileResource stylesheet = new FileResource(); + File stylesheetFile = new File(styleDir, xslname); + stylesheet.setFile(stylesheetFile); + return stylesheet; + } + + + /** check for invalid options + * @throws BuildException if something goes wrong. + */ protected void checkOptions() throws BuildException { // set the destination directory relative from the project if needed. if (toDir == null) { @@ -167,6 +309,7 @@ public class AggregateTransformer { * name and styledir. If no styledir is defined it will load * it as a java resource in the xsl child package, otherwise it * will get it from the given directory. + * @return system ID of the stylesheet. * @throws IOException thrown if the requested stylesheet does * not exist. */ diff --git a/src/main/org/apache/tools/ant/taskdefs/optional/junit/XMLResultAggregator.java b/src/main/org/apache/tools/ant/taskdefs/optional/junit/XMLResultAggregator.java index 599061b04..bf9cb0d88 100644 --- a/src/main/org/apache/tools/ant/taskdefs/optional/junit/XMLResultAggregator.java +++ b/src/main/org/apache/tools/ant/taskdefs/optional/junit/XMLResultAggregator.java @@ -1,5 +1,5 @@ /* - * Copyright 2001-2005 The Apache Software Foundation + * Copyright 2001-2006 The Apache Software Foundation * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -158,7 +158,7 @@ public class XMLResultAggregator extends Task implements XMLConstants { * the todir and tofile attributes. * @return the destination file where should be written the result file. */ - protected File getDestinationFile() { + public File getDestinationFile() { if (toFile == null) { toFile = DEFAULT_FILENAME; } diff --git a/src/main/org/apache/tools/ant/taskdefs/optional/junit/Xalan2Executor.java b/src/main/org/apache/tools/ant/taskdefs/optional/junit/Xalan2Executor.java index 316065e5a..1184b6b0e 100644 --- a/src/main/org/apache/tools/ant/taskdefs/optional/junit/Xalan2Executor.java +++ b/src/main/org/apache/tools/ant/taskdefs/optional/junit/Xalan2Executor.java @@ -1,5 +1,5 @@ /* - * Copyright 2001-2002,2004 The Apache Software Foundation + * Copyright 2001-2002,2004,2006 The Apache Software Foundation * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -28,8 +28,10 @@ import javax.xml.transform.stream.StreamSource; import org.apache.tools.ant.BuildException; /** - * Xalan executor via JAXP. Nothing special must exists in the classpath - * besides of course, a parser, jaxp and xalan. + * This class is not used by the framework any more. + * We plan to remove it in Ant 1.8 + * @deprecated since Ant 1.7 + * * * @ant.task ignore="true" */ diff --git a/src/main/org/apache/tools/ant/taskdefs/optional/junit/XalanExecutor.java b/src/main/org/apache/tools/ant/taskdefs/optional/junit/XalanExecutor.java index ebc8370c4..2788f46d7 100644 --- a/src/main/org/apache/tools/ant/taskdefs/optional/junit/XalanExecutor.java +++ b/src/main/org/apache/tools/ant/taskdefs/optional/junit/XalanExecutor.java @@ -1,5 +1,5 @@ /* - * Copyright 2001-2005 The Apache Software Foundation + * Copyright 2001-2006 The Apache Software Foundation * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -27,10 +27,10 @@ import org.apache.tools.ant.BuildException; import org.apache.tools.ant.Project; /** - * Command class that encapsulate specific behavior for each - * Xalan version. The right executor will be instantiated at - * runtime via class lookup. For instance, it will check first - * for Xalan2/XSLTC, then for Xalan1. + * This class is not used by the framework any more. + * We plan to remove it in Ant 1.8 + * @deprecated since Ant 1.7 + * */ abstract class XalanExecutor { private static final String PACKAGE = diff --git a/src/testcases/org/apache/tools/ant/taskdefs/optional/junit/JUnitReportTest.java b/src/testcases/org/apache/tools/ant/taskdefs/optional/junit/JUnitReportTest.java index 6982b868c..bb99beeba 100644 --- a/src/testcases/org/apache/tools/ant/taskdefs/optional/junit/JUnitReportTest.java +++ b/src/testcases/org/apache/tools/ant/taskdefs/optional/junit/JUnitReportTest.java @@ -122,6 +122,7 @@ public class JUnitReportTest extends BuildFileTest { InputStream reportStream = reportUrl.openStream(); assertTrue("This shouldnt be an empty stream.", reportStream.available() > 0); } + public void testSpecialSignsInHtmlPath() throws Exception { executeTarget("testSpecialSignsInHtmlPath"); File reportFile = new File(System.getProperty("root"), "src/etc/testcases/taskdefs/optional/junitreport/test/html# $%\u00A7&-!report/index.html"); @@ -134,4 +135,44 @@ public class JUnitReportTest extends BuildFileTest { InputStream reportStream = reportUrl.openStream(); assertTrue("This shouldnt be an empty stream.", reportStream.available() > 0); } -} \ No newline at end of file + + //Bugzilla Report 39708 + public void testWithStyleFromDir() throws Exception { + executeTarget("testWithStyleFromDir"); + File reportFile = new File(System.getProperty("root"), "src/etc/testcases/taskdefs/optional/junitreport/test/html/index.html"); + // tests one the file object + assertTrue("No index.html present. Not generated?", reportFile.exists() ); + assertTrue("Cant read the report file.", reportFile.canRead() ); + assertTrue("File shouldnt be empty.", reportFile.length() > 0 ); + // conversion to URL via FileUtils like in XMLResultAggregator, not as suggested in the bug report + URL reportUrl = new URL( FileUtils.getFileUtils().toURI(reportFile.getAbsolutePath()) ); + InputStream reportStream = reportUrl.openStream(); + assertTrue("This shouldnt be an empty stream.", reportStream.available() > 0); + } + + public void testWithStyleFromClasspath() throws Exception { + executeTarget("testWithStyleFromClasspath"); + File reportFile = new File(System.getProperty("root"), "src/etc/testcases/taskdefs/optional/junitreport/test/html/index.html"); + // tests one the file object + assertTrue("No index.html present. Not generated?", reportFile.exists() ); + assertTrue("Cant read the report file.", reportFile.canRead() ); + assertTrue("File shouldnt be empty.", reportFile.length() > 0 ); + // conversion to URL via FileUtils like in XMLResultAggregator, not as suggested in the bug report + URL reportUrl = new URL( FileUtils.getFileUtils().toURI(reportFile.getAbsolutePath()) ); + InputStream reportStream = reportUrl.openStream(); + assertTrue("This shouldnt be an empty stream.", reportStream.available() > 0); + } + + public void testWithParams() throws Exception { + expectLogContaining("testWithParams", "key1=value1,key2=value2"); + File reportFile = new File(System.getProperty("root"), "src/etc/testcases/taskdefs/optional/junitreport/test/html/index.html"); + // tests one the file object + assertTrue("No index.html present. Not generated?", reportFile.exists() ); + assertTrue("Cant read the report file.", reportFile.canRead() ); + assertTrue("File shouldnt be empty.", reportFile.length() > 0 ); + // conversion to URL via FileUtils like in XMLResultAggregator, not as suggested in the bug report + URL reportUrl = new URL( FileUtils.getFileUtils().toURI(reportFile.getAbsolutePath()) ); + InputStream reportStream = reportUrl.openStream(); + assertTrue("This shouldnt be an empty stream.", reportStream.available() > 0); + } +}